| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * Copyright 2016-2018 NXP
- * Copyright 2018, Sensor-Technik Wiedemann GmbH
- * Copyright 2018-2019, Vladimir Oltean <olteanv@gmail.com>
- * Copyright 2020-2021 NXP
- *
- * Ported from Linux (drivers/net/dsa/sja1105/).
- */
- #include <common.h>
- #include <dm/device_compat.h>
- #include <linux/bitops.h>
- #include <linux/bitrev.h>
- #include <linux/errno.h>
- #include <linux/delay.h>
- #include <linux/if_ether.h>
- #include <linux/if_vlan.h>
- #include <linux/types.h>
- #include <net/dsa.h>
- #include <stdlib.h>
- #include <spi.h>
- #include <miiphy.h>
- #include <dm/of_extra.h>
- enum packing_op {
- PACK,
- UNPACK,
- };
- #define ETHER_CRC32_POLY 0x04C11DB7
- #define ETH_P_SJA1105 0xdadb
- #define SJA1105_NUM_PORTS 5
- #define SJA1110_NUM_PORTS 11
- #define SJA1105_MAX_NUM_PORTS SJA1110_NUM_PORTS
- #define SJA1105_NUM_TC 8
- #define SJA1105ET_FDB_BIN_SIZE 4
- #define SJA1105_SIZE_CGU_CMD 4
- #define SJA1105_SIZE_RESET_CMD 4
- #define SJA1105_SIZE_MDIO_CMD 4
- #define SJA1105_SIZE_SPI_MSG_HEADER 4
- #define SJA1105_SIZE_SPI_MSG_MAXLEN (64 * 4)
- #define SJA1105_SIZE_DEVICE_ID 4
- #define SJA1105_SIZE_TABLE_HEADER 12
- #define SJA1105_SIZE_L2_POLICING_ENTRY 8
- #define SJA1105_SIZE_VLAN_LOOKUP_ENTRY 8
- #define SJA1110_SIZE_VLAN_LOOKUP_ENTRY 12
- #define SJA1105_SIZE_L2_FORWARDING_ENTRY 8
- #define SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY 12
- #define SJA1105_SIZE_XMII_PARAMS_ENTRY 4
- #define SJA1110_SIZE_XMII_PARAMS_ENTRY 8
- #define SJA1105ET_SIZE_MAC_CONFIG_ENTRY 28
- #define SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY 40
- #define SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY 32
- #define SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY 44
- #define SJA1110_SIZE_GENERAL_PARAMS_ENTRY 56
- #define SJA1105_MAX_L2_LOOKUP_COUNT 1024
- #define SJA1105_MAX_L2_POLICING_COUNT 45
- #define SJA1110_MAX_L2_POLICING_COUNT 110
- #define SJA1105_MAX_VLAN_LOOKUP_COUNT 4096
- #define SJA1105_MAX_L2_FORWARDING_COUNT 13
- #define SJA1110_MAX_L2_FORWARDING_COUNT 19
- #define SJA1105_MAX_MAC_CONFIG_COUNT 5
- #define SJA1110_MAX_MAC_CONFIG_COUNT 11
- #define SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT 1
- #define SJA1105_MAX_GENERAL_PARAMS_COUNT 1
- #define SJA1105_MAX_XMII_PARAMS_COUNT 1
- #define SJA1105_MAX_FRAME_MEMORY 929
- #define SJA1105E_DEVICE_ID 0x9C00000Cull
- #define SJA1105T_DEVICE_ID 0x9E00030Eull
- #define SJA1105PR_DEVICE_ID 0xAF00030Eull
- #define SJA1105QS_DEVICE_ID 0xAE00030Eull
- #define SJA1110_DEVICE_ID 0xB700030Full
- #define SJA1105ET_PART_NO 0x9A83
- #define SJA1105P_PART_NO 0x9A84
- #define SJA1105Q_PART_NO 0x9A85
- #define SJA1105R_PART_NO 0x9A86
- #define SJA1105S_PART_NO 0x9A87
- #define SJA1110A_PART_NO 0x1110
- #define SJA1110B_PART_NO 0x1111
- #define SJA1110C_PART_NO 0x1112
- #define SJA1110D_PART_NO 0x1113
- #define SJA1110_ACU 0x1c4400
- #define SJA1110_RGU 0x1c6000
- #define SJA1110_CGU 0x1c6400
- #define SJA1110_SPI_ADDR(x) ((x) / 4)
- #define SJA1110_ACU_ADDR(x) (SJA1110_ACU + SJA1110_SPI_ADDR(x))
- #define SJA1110_CGU_ADDR(x) (SJA1110_CGU + SJA1110_SPI_ADDR(x))
- #define SJA1110_RGU_ADDR(x) (SJA1110_RGU + SJA1110_SPI_ADDR(x))
- #define SJA1105_RSV_ADDR 0xffffffffffffffffull
- #define SJA1110_PCS_BANK_REG SJA1110_SPI_ADDR(0x3fc)
- #define DSA_8021Q_DIR_TX BIT(11)
- #define DSA_8021Q_PORT_SHIFT 0
- #define DSA_8021Q_PORT_MASK GENMASK(3, 0)
- #define DSA_8021Q_PORT(x) (((x) << DSA_8021Q_PORT_SHIFT) & \
- DSA_8021Q_PORT_MASK)
- #define SJA1105_RATE_MBPS(speed) (((speed) * 64000) / 1000)
- /* XPCS registers */
- /* VR MII MMD registers offsets */
- #define DW_VR_MII_DIG_CTRL1 0x8000
- #define DW_VR_MII_AN_CTRL 0x8001
- #define DW_VR_MII_DIG_CTRL2 0x80e1
- /* VR_MII_DIG_CTRL1 */
- #define DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW BIT(9)
- /* VR_MII_DIG_CTRL2 */
- #define DW_VR_MII_DIG_CTRL2_TX_POL_INV BIT(4)
- /* VR_MII_AN_CTRL */
- #define DW_VR_MII_AN_CTRL_TX_CONFIG_SHIFT 3
- #define DW_VR_MII_TX_CONFIG_MASK BIT(3)
- #define DW_VR_MII_TX_CONFIG_MAC_SIDE_SGMII 0x0
- #define DW_VR_MII_AN_CTRL_PCS_MODE_SHIFT 1
- #define DW_VR_MII_PCS_MODE_MASK GENMASK(2, 1)
- #define DW_VR_MII_PCS_MODE_C37_SGMII 0x2
- /* PMA registers */
- /* LANE_DRIVER1_0 register */
- #define SJA1110_LANE_DRIVER1_0 0x8038
- #define SJA1110_TXDRV(x) (((x) << 12) & GENMASK(14, 12))
- /* LANE_DRIVER2_0 register */
- #define SJA1110_LANE_DRIVER2_0 0x803a
- #define SJA1110_TXDRVTRIM_LSB(x) ((x) & GENMASK_ULL(15, 0))
- /* LANE_DRIVER2_1 register */
- #define SJA1110_LANE_DRIVER2_1 0x803b
- #define SJA1110_LANE_DRIVER2_1_RSV BIT(9)
- #define SJA1110_TXDRVTRIM_MSB(x) (((x) & GENMASK_ULL(23, 16)) >> 16)
- /* LANE_TRIM register */
- #define SJA1110_LANE_TRIM 0x8040
- #define SJA1110_TXTEN BIT(11)
- #define SJA1110_TXRTRIM(x) (((x) << 8) & GENMASK(10, 8))
- #define SJA1110_TXPLL_BWSEL BIT(7)
- #define SJA1110_RXTEN BIT(6)
- #define SJA1110_RXRTRIM(x) (((x) << 3) & GENMASK(5, 3))
- #define SJA1110_CDR_GAIN BIT(2)
- #define SJA1110_ACCOUPLE_RXVCM_EN BIT(0)
- /* LANE_DATAPATH_1 register */
- #define SJA1110_LANE_DATAPATH_1 0x8037
- /* POWERDOWN_ENABLE register */
- #define SJA1110_POWERDOWN_ENABLE 0x8041
- #define SJA1110_TXPLL_PD BIT(12)
- #define SJA1110_TXPD BIT(11)
- #define SJA1110_RXPKDETEN BIT(10)
- #define SJA1110_RXCH_PD BIT(9)
- #define SJA1110_RXBIAS_PD BIT(8)
- #define SJA1110_RESET_SER_EN BIT(7)
- #define SJA1110_RESET_SER BIT(6)
- #define SJA1110_RESET_DES BIT(5)
- #define SJA1110_RCVEN BIT(4)
- /* RXPLL_CTRL0 register */
- #define SJA1110_RXPLL_CTRL0 0x8065
- #define SJA1110_RXPLL_FBDIV(x) (((x) << 2) & GENMASK(9, 2))
- /* RXPLL_CTRL1 register */
- #define SJA1110_RXPLL_CTRL1 0x8066
- #define SJA1110_RXPLL_REFDIV(x) ((x) & GENMASK(4, 0))
- /* TXPLL_CTRL0 register */
- #define SJA1110_TXPLL_CTRL0 0x806d
- #define SJA1110_TXPLL_FBDIV(x) ((x) & GENMASK(11, 0))
- /* TXPLL_CTRL1 register */
- #define SJA1110_TXPLL_CTRL1 0x806e
- #define SJA1110_TXPLL_REFDIV(x) ((x) & GENMASK(5, 0))
- /* RX_DATA_DETECT register */
- #define SJA1110_RX_DATA_DETECT 0x8045
- /* RX_CDR_CTLE register */
- #define SJA1110_RX_CDR_CTLE 0x8042
- /* UM10944.pdf Page 11, Table 2. Configuration Blocks */
- enum {
- BLKID_L2_POLICING = 0x06,
- BLKID_VLAN_LOOKUP = 0x07,
- BLKID_L2_FORWARDING = 0x08,
- BLKID_MAC_CONFIG = 0x09,
- BLKID_L2_FORWARDING_PARAMS = 0x0E,
- BLKID_GENERAL_PARAMS = 0x11,
- BLKID_XMII_PARAMS = 0x4E,
- };
- enum sja1105_blk_idx {
- BLK_IDX_L2_POLICING = 0,
- BLK_IDX_VLAN_LOOKUP,
- BLK_IDX_L2_FORWARDING,
- BLK_IDX_MAC_CONFIG,
- BLK_IDX_L2_FORWARDING_PARAMS,
- BLK_IDX_GENERAL_PARAMS,
- BLK_IDX_XMII_PARAMS,
- BLK_IDX_MAX,
- };
- struct sja1105_general_params_entry {
- u64 mac_fltres1;
- u64 mac_fltres0;
- u64 mac_flt1;
- u64 mac_flt0;
- u64 casc_port;
- u64 host_port;
- u64 mirr_port;
- u64 tpid;
- u64 tpid2;
- };
- struct sja1105_vlan_lookup_entry {
- u64 vmemb_port;
- u64 vlan_bc;
- u64 tag_port;
- u64 vlanid;
- u64 type_entry; /* SJA1110 only */
- };
- struct sja1105_l2_forwarding_entry {
- u64 bc_domain;
- u64 reach_port;
- u64 fl_domain;
- };
- struct sja1105_l2_forwarding_params_entry {
- u64 part_spc[SJA1105_NUM_TC];
- };
- struct sja1105_l2_policing_entry {
- u64 sharindx;
- u64 smax;
- u64 rate;
- u64 maxlen;
- u64 partition;
- };
- struct sja1105_mac_config_entry {
- u64 top[SJA1105_NUM_TC];
- u64 base[SJA1105_NUM_TC];
- u64 enabled[SJA1105_NUM_TC];
- u64 speed;
- u64 vlanid;
- u64 egress;
- u64 ingress;
- };
- struct sja1105_xmii_params_entry {
- u64 phy_mac[SJA1105_MAX_NUM_PORTS];
- u64 xmii_mode[SJA1105_MAX_NUM_PORTS];
- u64 special[SJA1105_MAX_NUM_PORTS];
- };
- struct sja1105_table_header {
- u64 block_id;
- u64 len;
- u64 crc;
- };
- struct sja1105_table_ops {
- size_t (*packing)(void *buf, void *entry_ptr, enum packing_op op);
- size_t unpacked_entry_size;
- size_t packed_entry_size;
- size_t max_entry_count;
- };
- struct sja1105_table {
- const struct sja1105_table_ops *ops;
- size_t entry_count;
- void *entries;
- };
- struct sja1105_static_config {
- u64 device_id;
- struct sja1105_table tables[BLK_IDX_MAX];
- };
- struct sja1105_xpcs_cfg {
- bool inband_an;
- int speed;
- };
- struct sja1105_private {
- struct sja1105_static_config static_config;
- bool rgmii_rx_delay[SJA1105_MAX_NUM_PORTS];
- bool rgmii_tx_delay[SJA1105_MAX_NUM_PORTS];
- u16 pvid[SJA1105_MAX_NUM_PORTS];
- struct sja1105_xpcs_cfg xpcs_cfg[SJA1105_MAX_NUM_PORTS];
- struct mii_dev *mdio_pcs;
- const struct sja1105_info *info;
- struct udevice *dev;
- };
- typedef enum {
- SPI_READ = 0,
- SPI_WRITE = 1,
- } sja1105_spi_rw_mode_t;
- typedef enum {
- XMII_MAC = 0,
- XMII_PHY = 1,
- } sja1105_mii_role_t;
- typedef enum {
- XMII_MODE_MII = 0,
- XMII_MODE_RMII = 1,
- XMII_MODE_RGMII = 2,
- XMII_MODE_SGMII = 3,
- } sja1105_phy_interface_t;
- enum {
- SJA1105_SPEED_AUTO,
- SJA1105_SPEED_10MBPS,
- SJA1105_SPEED_100MBPS,
- SJA1105_SPEED_1000MBPS,
- SJA1105_SPEED_MAX,
- };
- enum sja1110_vlan_type {
- SJA1110_VLAN_INVALID = 0,
- SJA1110_VLAN_C_TAG = 1, /* Single inner VLAN tag */
- SJA1110_VLAN_S_TAG = 2, /* Single outer VLAN tag */
- SJA1110_VLAN_D_TAG = 3, /* Double tagged, use outer tag for lookup */
- };
- /* Keeps the different addresses between E/T and P/Q/R/S */
- struct sja1105_regs {
- u64 device_id;
- u64 prod_id;
- u64 status;
- u64 port_control;
- u64 rgu;
- u64 config;
- u64 rmii_pll1;
- u64 pad_mii_tx[SJA1105_MAX_NUM_PORTS];
- u64 pad_mii_rx[SJA1105_MAX_NUM_PORTS];
- u64 pad_mii_id[SJA1105_MAX_NUM_PORTS];
- u64 cgu_idiv[SJA1105_MAX_NUM_PORTS];
- u64 mii_tx_clk[SJA1105_MAX_NUM_PORTS];
- u64 mii_rx_clk[SJA1105_MAX_NUM_PORTS];
- u64 mii_ext_tx_clk[SJA1105_MAX_NUM_PORTS];
- u64 mii_ext_rx_clk[SJA1105_MAX_NUM_PORTS];
- u64 rgmii_tx_clk[SJA1105_MAX_NUM_PORTS];
- u64 rmii_ref_clk[SJA1105_MAX_NUM_PORTS];
- u64 rmii_ext_tx_clk[SJA1105_MAX_NUM_PORTS];
- u64 pcs_base[SJA1105_MAX_NUM_PORTS];
- };
- struct sja1105_info {
- u64 device_id;
- u64 part_no;
- const struct sja1105_table_ops *static_ops;
- const struct sja1105_regs *regs;
- int (*reset_cmd)(struct sja1105_private *priv);
- int (*setup_rgmii_delay)(struct sja1105_private *priv, int port);
- int (*pcs_mdio_read)(struct mii_dev *bus, int phy, int mmd, int reg);
- int (*pcs_mdio_write)(struct mii_dev *bus, int phy, int mmd, int reg,
- u16 val);
- int (*pma_config)(struct sja1105_private *priv, int port);
- const char *name;
- bool supports_mii[SJA1105_MAX_NUM_PORTS];
- bool supports_rmii[SJA1105_MAX_NUM_PORTS];
- bool supports_rgmii[SJA1105_MAX_NUM_PORTS];
- bool supports_sgmii[SJA1105_MAX_NUM_PORTS];
- const u64 port_speed[SJA1105_SPEED_MAX];
- };
- struct sja1105_chunk {
- u8 *buf;
- size_t len;
- u64 reg_addr;
- };
- struct sja1105_spi_message {
- u64 access;
- u64 read_count;
- u64 address;
- };
- /* Common structure for CFG_PAD_MIIx_RX and CFG_PAD_MIIx_TX */
- struct sja1105_cfg_pad_mii {
- u64 d32_os;
- u64 d32_ih;
- u64 d32_ipud;
- u64 d10_ih;
- u64 d10_os;
- u64 d10_ipud;
- u64 ctrl_os;
- u64 ctrl_ih;
- u64 ctrl_ipud;
- u64 clk_os;
- u64 clk_ih;
- u64 clk_ipud;
- };
- struct sja1105_cfg_pad_mii_id {
- u64 rxc_stable_ovr;
- u64 rxc_delay;
- u64 rxc_bypass;
- u64 rxc_pd;
- u64 txc_stable_ovr;
- u64 txc_delay;
- u64 txc_bypass;
- u64 txc_pd;
- };
- struct sja1105_cgu_idiv {
- u64 clksrc;
- u64 autoblock;
- u64 idiv;
- u64 pd;
- };
- struct sja1105_cgu_pll_ctrl {
- u64 pllclksrc;
- u64 msel;
- u64 autoblock;
- u64 psel;
- u64 direct;
- u64 fbsel;
- u64 bypass;
- u64 pd;
- };
- enum {
- CLKSRC_MII0_TX_CLK = 0x00,
- CLKSRC_MII0_RX_CLK = 0x01,
- CLKSRC_MII1_TX_CLK = 0x02,
- CLKSRC_MII1_RX_CLK = 0x03,
- CLKSRC_MII2_TX_CLK = 0x04,
- CLKSRC_MII2_RX_CLK = 0x05,
- CLKSRC_MII3_TX_CLK = 0x06,
- CLKSRC_MII3_RX_CLK = 0x07,
- CLKSRC_MII4_TX_CLK = 0x08,
- CLKSRC_MII4_RX_CLK = 0x09,
- CLKSRC_PLL0 = 0x0B,
- CLKSRC_PLL1 = 0x0E,
- CLKSRC_IDIV0 = 0x11,
- CLKSRC_IDIV1 = 0x12,
- CLKSRC_IDIV2 = 0x13,
- CLKSRC_IDIV3 = 0x14,
- CLKSRC_IDIV4 = 0x15,
- };
- struct sja1105_cgu_mii_ctrl {
- u64 clksrc;
- u64 autoblock;
- u64 pd;
- };
- static int get_reverse_lsw32_offset(int offset, size_t len)
- {
- int closest_multiple_of_4;
- int word_index;
- word_index = offset / 4;
- closest_multiple_of_4 = word_index * 4;
- offset -= closest_multiple_of_4;
- word_index = (len / 4) - word_index - 1;
- return word_index * 4 + offset;
- }
- /* Simplified version of the "packing" function from Linux, adapted
- * to support only sja1105's quirk: QUIRK_LSW32_IS_FIRST
- */
- static void sja1105_packing(void *pbuf, u64 *uval, int startbit, int endbit,
- size_t pbuflen, enum packing_op op)
- {
- int plogical_first_u8, plogical_last_u8, box;
- if (op == UNPACK)
- *uval = 0;
- plogical_first_u8 = startbit / 8;
- plogical_last_u8 = endbit / 8;
- for (box = plogical_first_u8; box >= plogical_last_u8; box--) {
- int box_start_bit, box_end_bit, box_addr;
- int proj_start_bit, proj_end_bit;
- u64 proj_mask;
- u8 box_mask;
- if (box == plogical_first_u8)
- box_start_bit = startbit % 8;
- else
- box_start_bit = 7;
- if (box == plogical_last_u8)
- box_end_bit = endbit % 8;
- else
- box_end_bit = 0;
- proj_start_bit = ((box * 8) + box_start_bit) - endbit;
- proj_end_bit = ((box * 8) + box_end_bit) - endbit;
- proj_mask = GENMASK_ULL(proj_start_bit, proj_end_bit);
- box_mask = GENMASK_ULL(box_start_bit, box_end_bit);
- box_addr = pbuflen - box - 1;
- box_addr = get_reverse_lsw32_offset(box_addr, pbuflen);
- if (op == UNPACK) {
- u64 pval;
- /* Read from pbuf, write to uval */
- pval = ((u8 *)pbuf)[box_addr] & box_mask;
- pval >>= box_end_bit;
- pval <<= proj_end_bit;
- *uval &= ~proj_mask;
- *uval |= pval;
- } else {
- u64 pval;
- /* Write to pbuf, read from uval */
- pval = (*uval) & proj_mask;
- pval >>= proj_end_bit;
- pval <<= box_end_bit;
- ((u8 *)pbuf)[box_addr] &= ~box_mask;
- ((u8 *)pbuf)[box_addr] |= pval;
- }
- }
- }
- static u32 crc32_add(u32 crc, u8 byte)
- {
- u32 byte32 = bitrev32(byte);
- int i;
- for (i = 0; i < 8; i++) {
- if ((crc ^ byte32) & BIT(31)) {
- crc <<= 1;
- crc ^= ETHER_CRC32_POLY;
- } else {
- crc <<= 1;
- }
- byte32 <<= 1;
- }
- return crc;
- }
- /* Little-endian Ethernet CRC32 of data packed as big-endian u32 words */
- static uint32_t sja1105_crc32(void *buf, size_t len)
- {
- unsigned int i;
- u64 chunk;
- u32 crc;
- /* seed */
- crc = 0xFFFFFFFF;
- for (i = 0; i < len; i += 4) {
- sja1105_packing(buf + i, &chunk, 31, 0, 4, UNPACK);
- crc = crc32_add(crc, chunk & 0xFF);
- crc = crc32_add(crc, (chunk >> 8) & 0xFF);
- crc = crc32_add(crc, (chunk >> 16) & 0xFF);
- crc = crc32_add(crc, (chunk >> 24) & 0xFF);
- }
- return bitrev32(~crc);
- }
- static void sja1105_spi_message_pack(void *buf, struct sja1105_spi_message *msg)
- {
- const int size = SJA1105_SIZE_SPI_MSG_HEADER;
- memset(buf, 0, size);
- sja1105_packing(buf, &msg->access, 31, 31, size, PACK);
- sja1105_packing(buf, &msg->read_count, 30, 25, size, PACK);
- sja1105_packing(buf, &msg->address, 24, 4, size, PACK);
- }
- static int sja1105_xfer_buf(const struct sja1105_private *priv,
- sja1105_spi_rw_mode_t rw, u64 reg_addr,
- u8 *buf, size_t len)
- {
- struct udevice *dev = priv->dev;
- struct sja1105_chunk chunk = {
- .len = min_t(size_t, len, SJA1105_SIZE_SPI_MSG_MAXLEN),
- .reg_addr = reg_addr,
- .buf = buf,
- };
- int num_chunks;
- int rc, i;
- rc = dm_spi_claim_bus(dev);
- if (rc)
- return rc;
- num_chunks = DIV_ROUND_UP(len, SJA1105_SIZE_SPI_MSG_MAXLEN);
- for (i = 0; i < num_chunks; i++) {
- u8 hdr_buf[SJA1105_SIZE_SPI_MSG_HEADER];
- struct sja1105_spi_message msg;
- u8 *rx_buf = NULL;
- u8 *tx_buf = NULL;
- /* Populate the transfer's header buffer */
- msg.address = chunk.reg_addr;
- msg.access = rw;
- if (rw == SPI_READ)
- msg.read_count = chunk.len / 4;
- else
- /* Ignored */
- msg.read_count = 0;
- sja1105_spi_message_pack(hdr_buf, &msg);
- rc = dm_spi_xfer(dev, SJA1105_SIZE_SPI_MSG_HEADER * 8, hdr_buf,
- NULL, SPI_XFER_BEGIN);
- if (rc)
- goto out;
- /* Populate the transfer's data buffer */
- if (rw == SPI_READ)
- rx_buf = chunk.buf;
- else
- tx_buf = chunk.buf;
- rc = dm_spi_xfer(dev, chunk.len * 8, tx_buf, rx_buf,
- SPI_XFER_END);
- if (rc)
- goto out;
- /* Calculate next chunk */
- chunk.buf += chunk.len;
- chunk.reg_addr += chunk.len / 4;
- chunk.len = min_t(size_t, (ptrdiff_t)(buf + len - chunk.buf),
- SJA1105_SIZE_SPI_MSG_MAXLEN);
- }
- out:
- dm_spi_release_bus(dev);
- return rc;
- }
- static int sja1105et_reset_cmd(struct sja1105_private *priv)
- {
- const struct sja1105_regs *regs = priv->info->regs;
- u8 packed_buf[SJA1105_SIZE_RESET_CMD] = {0};
- const int size = SJA1105_SIZE_RESET_CMD;
- u64 cold_rst = 1;
- sja1105_packing(packed_buf, &cold_rst, 3, 3, size, PACK);
- return sja1105_xfer_buf(priv, SPI_WRITE, regs->rgu, packed_buf,
- SJA1105_SIZE_RESET_CMD);
- }
- static int sja1105pqrs_reset_cmd(struct sja1105_private *priv)
- {
- const struct sja1105_regs *regs = priv->info->regs;
- u8 packed_buf[SJA1105_SIZE_RESET_CMD] = {0};
- const int size = SJA1105_SIZE_RESET_CMD;
- u64 cold_rst = 1;
- sja1105_packing(packed_buf, &cold_rst, 2, 2, size, PACK);
- return sja1105_xfer_buf(priv, SPI_WRITE, regs->rgu, packed_buf,
- SJA1105_SIZE_RESET_CMD);
- }
- static int sja1110_reset_cmd(struct sja1105_private *priv)
- {
- const struct sja1105_regs *regs = priv->info->regs;
- u8 packed_buf[SJA1105_SIZE_RESET_CMD] = {0};
- const int size = SJA1105_SIZE_RESET_CMD;
- u64 switch_rst = 1;
- /* Only reset the switch core.
- * A full cold reset would re-enable the BASE_MCSS_CLOCK PLL which
- * would turn on the microcontroller, potentially letting it execute
- * code which could interfere with our configuration.
- */
- sja1105_packing(packed_buf, &switch_rst, 20, 20, size, PACK);
- return sja1105_xfer_buf(priv, SPI_WRITE, regs->rgu, packed_buf,
- SJA1105_SIZE_RESET_CMD);
- }
- static size_t sja1105et_general_params_entry_packing(void *buf, void *entry_ptr,
- enum packing_op op)
- {
- const size_t size = SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY;
- struct sja1105_general_params_entry *entry = entry_ptr;
- sja1105_packing(buf, &entry->mac_fltres1, 311, 264, size, op);
- sja1105_packing(buf, &entry->mac_fltres0, 263, 216, size, op);
- sja1105_packing(buf, &entry->mac_flt1, 215, 168, size, op);
- sja1105_packing(buf, &entry->mac_flt0, 167, 120, size, op);
- sja1105_packing(buf, &entry->casc_port, 115, 113, size, op);
- sja1105_packing(buf, &entry->host_port, 112, 110, size, op);
- sja1105_packing(buf, &entry->mirr_port, 109, 107, size, op);
- sja1105_packing(buf, &entry->tpid, 42, 27, size, op);
- sja1105_packing(buf, &entry->tpid2, 25, 10, size, op);
- return size;
- }
- static size_t sja1110_general_params_entry_packing(void *buf, void *entry_ptr,
- enum packing_op op)
- {
- struct sja1105_general_params_entry *entry = entry_ptr;
- const size_t size = SJA1110_SIZE_GENERAL_PARAMS_ENTRY;
- sja1105_packing(buf, &entry->mac_fltres1, 438, 391, size, op);
- sja1105_packing(buf, &entry->mac_fltres0, 390, 343, size, op);
- sja1105_packing(buf, &entry->mac_flt1, 342, 295, size, op);
- sja1105_packing(buf, &entry->mac_flt0, 294, 247, size, op);
- sja1105_packing(buf, &entry->casc_port, 242, 232, size, op);
- sja1105_packing(buf, &entry->host_port, 231, 228, size, op);
- sja1105_packing(buf, &entry->mirr_port, 227, 224, size, op);
- sja1105_packing(buf, &entry->tpid2, 159, 144, size, op);
- sja1105_packing(buf, &entry->tpid, 142, 127, size, op);
- return size;
- }
- static size_t
- sja1105pqrs_general_params_entry_packing(void *buf, void *entry_ptr,
- enum packing_op op)
- {
- const size_t size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY;
- struct sja1105_general_params_entry *entry = entry_ptr;
- sja1105_packing(buf, &entry->mac_fltres1, 343, 296, size, op);
- sja1105_packing(buf, &entry->mac_fltres0, 295, 248, size, op);
- sja1105_packing(buf, &entry->mac_flt1, 247, 200, size, op);
- sja1105_packing(buf, &entry->mac_flt0, 199, 152, size, op);
- sja1105_packing(buf, &entry->casc_port, 147, 145, size, op);
- sja1105_packing(buf, &entry->host_port, 144, 142, size, op);
- sja1105_packing(buf, &entry->mirr_port, 141, 139, size, op);
- sja1105_packing(buf, &entry->tpid, 74, 59, size, op);
- sja1105_packing(buf, &entry->tpid2, 57, 42, size, op);
- return size;
- }
- static size_t
- sja1105_l2_forwarding_params_entry_packing(void *buf, void *entry_ptr,
- enum packing_op op)
- {
- const size_t size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY;
- struct sja1105_l2_forwarding_params_entry *entry = entry_ptr;
- int offset, i;
- for (i = 0, offset = 13; i < SJA1105_NUM_TC; i++, offset += 10)
- sja1105_packing(buf, &entry->part_spc[i],
- offset + 9, offset + 0, size, op);
- return size;
- }
- static size_t
- sja1110_l2_forwarding_params_entry_packing(void *buf, void *entry_ptr,
- enum packing_op op)
- {
- struct sja1105_l2_forwarding_params_entry *entry = entry_ptr;
- const size_t size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY;
- int offset, i;
- for (i = 0, offset = 5; i < 8; i++, offset += 11)
- sja1105_packing(buf, &entry->part_spc[i],
- offset + 10, offset + 0, size, op);
- return size;
- }
- static size_t sja1105_l2_forwarding_entry_packing(void *buf, void *entry_ptr,
- enum packing_op op)
- {
- const size_t size = SJA1105_SIZE_L2_FORWARDING_ENTRY;
- struct sja1105_l2_forwarding_entry *entry = entry_ptr;
- sja1105_packing(buf, &entry->bc_domain, 63, 59, size, op);
- sja1105_packing(buf, &entry->reach_port, 58, 54, size, op);
- sja1105_packing(buf, &entry->fl_domain, 53, 49, size, op);
- return size;
- }
- static size_t sja1110_l2_forwarding_entry_packing(void *buf, void *entry_ptr,
- enum packing_op op)
- {
- struct sja1105_l2_forwarding_entry *entry = entry_ptr;
- const size_t size = SJA1105_SIZE_L2_FORWARDING_ENTRY;
- sja1105_packing(buf, &entry->bc_domain, 63, 53, size, op);
- sja1105_packing(buf, &entry->reach_port, 52, 42, size, op);
- sja1105_packing(buf, &entry->fl_domain, 41, 31, size, op);
- return size;
- }
- static size_t sja1105_l2_policing_entry_packing(void *buf, void *entry_ptr,
- enum packing_op op)
- {
- struct sja1105_l2_policing_entry *entry = entry_ptr;
- const size_t size = SJA1105_SIZE_L2_POLICING_ENTRY;
- sja1105_packing(buf, &entry->sharindx, 63, 58, size, op);
- sja1105_packing(buf, &entry->smax, 57, 42, size, op);
- sja1105_packing(buf, &entry->rate, 41, 26, size, op);
- sja1105_packing(buf, &entry->maxlen, 25, 15, size, op);
- sja1105_packing(buf, &entry->partition, 14, 12, size, op);
- return size;
- }
- static size_t sja1110_l2_policing_entry_packing(void *buf, void *entry_ptr,
- enum packing_op op)
- {
- struct sja1105_l2_policing_entry *entry = entry_ptr;
- const size_t size = SJA1105_SIZE_L2_POLICING_ENTRY;
- sja1105_packing(buf, &entry->sharindx, 63, 57, size, op);
- sja1105_packing(buf, &entry->smax, 56, 39, size, op);
- sja1105_packing(buf, &entry->rate, 38, 21, size, op);
- sja1105_packing(buf, &entry->maxlen, 20, 10, size, op);
- sja1105_packing(buf, &entry->partition, 9, 7, size, op);
- return size;
- }
- static size_t sja1105et_mac_config_entry_packing(void *buf, void *entry_ptr,
- enum packing_op op)
- {
- const size_t size = SJA1105ET_SIZE_MAC_CONFIG_ENTRY;
- struct sja1105_mac_config_entry *entry = entry_ptr;
- int offset, i;
- for (i = 0, offset = 72; i < SJA1105_NUM_TC; i++, offset += 19) {
- sja1105_packing(buf, &entry->enabled[i],
- offset + 0, offset + 0, size, op);
- sja1105_packing(buf, &entry->base[i],
- offset + 9, offset + 1, size, op);
- sja1105_packing(buf, &entry->top[i],
- offset + 18, offset + 10, size, op);
- }
- sja1105_packing(buf, &entry->speed, 66, 65, size, op);
- sja1105_packing(buf, &entry->vlanid, 21, 10, size, op);
- sja1105_packing(buf, &entry->egress, 2, 2, size, op);
- sja1105_packing(buf, &entry->ingress, 1, 1, size, op);
- return size;
- }
- static size_t sja1105pqrs_mac_config_entry_packing(void *buf, void *entry_ptr,
- enum packing_op op)
- {
- const size_t size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY;
- struct sja1105_mac_config_entry *entry = entry_ptr;
- int offset, i;
- for (i = 0, offset = 104; i < SJA1105_NUM_TC; i++, offset += 19) {
- sja1105_packing(buf, &entry->enabled[i],
- offset + 0, offset + 0, size, op);
- sja1105_packing(buf, &entry->base[i],
- offset + 9, offset + 1, size, op);
- sja1105_packing(buf, &entry->top[i],
- offset + 18, offset + 10, size, op);
- }
- sja1105_packing(buf, &entry->speed, 98, 97, size, op);
- sja1105_packing(buf, &entry->vlanid, 53, 42, size, op);
- sja1105_packing(buf, &entry->egress, 32, 32, size, op);
- sja1105_packing(buf, &entry->ingress, 31, 31, size, op);
- return size;
- }
- static size_t sja1110_mac_config_entry_packing(void *buf, void *entry_ptr,
- enum packing_op op)
- {
- const size_t size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY;
- struct sja1105_mac_config_entry *entry = entry_ptr;
- int offset, i;
- for (i = 0, offset = 104; i < 8; i++, offset += 19) {
- sja1105_packing(buf, &entry->enabled[i],
- offset + 0, offset + 0, size, op);
- sja1105_packing(buf, &entry->base[i],
- offset + 9, offset + 1, size, op);
- sja1105_packing(buf, &entry->top[i],
- offset + 18, offset + 10, size, op);
- }
- sja1105_packing(buf, &entry->speed, 98, 96, size, op);
- sja1105_packing(buf, &entry->vlanid, 52, 41, size, op);
- sja1105_packing(buf, &entry->egress, 31, 31, size, op);
- sja1105_packing(buf, &entry->ingress, 30, 30, size, op);
- return size;
- }
- static size_t sja1105_vlan_lookup_entry_packing(void *buf, void *entry_ptr,
- enum packing_op op)
- {
- const size_t size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY;
- struct sja1105_vlan_lookup_entry *entry = entry_ptr;
- sja1105_packing(buf, &entry->vmemb_port, 53, 49, size, op);
- sja1105_packing(buf, &entry->vlan_bc, 48, 44, size, op);
- sja1105_packing(buf, &entry->tag_port, 43, 39, size, op);
- sja1105_packing(buf, &entry->vlanid, 38, 27, size, op);
- return size;
- }
- static size_t sja1110_vlan_lookup_entry_packing(void *buf, void *entry_ptr,
- enum packing_op op)
- {
- struct sja1105_vlan_lookup_entry *entry = entry_ptr;
- const size_t size = SJA1110_SIZE_VLAN_LOOKUP_ENTRY;
- sja1105_packing(buf, &entry->vmemb_port, 73, 63, size, op);
- sja1105_packing(buf, &entry->vlan_bc, 62, 52, size, op);
- sja1105_packing(buf, &entry->tag_port, 51, 41, size, op);
- sja1105_packing(buf, &entry->type_entry, 40, 39, size, op);
- sja1105_packing(buf, &entry->vlanid, 38, 27, size, op);
- return size;
- }
- static size_t sja1105_xmii_params_entry_packing(void *buf, void *entry_ptr,
- enum packing_op op)
- {
- const size_t size = SJA1105_SIZE_XMII_PARAMS_ENTRY;
- struct sja1105_xmii_params_entry *entry = entry_ptr;
- int offset, i;
- for (i = 0, offset = 17; i < SJA1105_NUM_PORTS; i++, offset += 3) {
- sja1105_packing(buf, &entry->xmii_mode[i],
- offset + 1, offset + 0, size, op);
- sja1105_packing(buf, &entry->phy_mac[i],
- offset + 2, offset + 2, size, op);
- }
- return size;
- }
- static size_t sja1110_xmii_params_entry_packing(void *buf, void *entry_ptr,
- enum packing_op op)
- {
- const size_t size = SJA1110_SIZE_XMII_PARAMS_ENTRY;
- struct sja1105_xmii_params_entry *entry = entry_ptr;
- int offset, i;
- for (i = 0, offset = 20; i < SJA1110_NUM_PORTS; i++, offset += 4) {
- sja1105_packing(buf, &entry->xmii_mode[i],
- offset + 1, offset + 0, size, op);
- sja1105_packing(buf, &entry->phy_mac[i],
- offset + 2, offset + 2, size, op);
- sja1105_packing(buf, &entry->special[i],
- offset + 3, offset + 3, size, op);
- }
- return size;
- }
- static size_t sja1105_table_header_packing(void *buf, void *entry_ptr,
- enum packing_op op)
- {
- const size_t size = SJA1105_SIZE_TABLE_HEADER;
- struct sja1105_table_header *entry = entry_ptr;
- sja1105_packing(buf, &entry->block_id, 31, 24, size, op);
- sja1105_packing(buf, &entry->len, 55, 32, size, op);
- sja1105_packing(buf, &entry->crc, 95, 64, size, op);
- return size;
- }
- static void
- sja1105_table_header_pack_with_crc(void *buf, struct sja1105_table_header *hdr)
- {
- /* First pack the table as-is, then calculate the CRC, and
- * finally put the proper CRC into the packed buffer
- */
- memset(buf, 0, SJA1105_SIZE_TABLE_HEADER);
- sja1105_table_header_packing(buf, hdr, PACK);
- hdr->crc = sja1105_crc32(buf, SJA1105_SIZE_TABLE_HEADER - 4);
- sja1105_packing(buf + SJA1105_SIZE_TABLE_HEADER - 4, &hdr->crc,
- 31, 0, 4, PACK);
- }
- static void sja1105_table_write_crc(u8 *table_start, u8 *crc_ptr)
- {
- u64 computed_crc;
- int len_bytes;
- len_bytes = (uintptr_t)(crc_ptr - table_start);
- computed_crc = sja1105_crc32(table_start, len_bytes);
- sja1105_packing(crc_ptr, &computed_crc, 31, 0, 4, PACK);
- }
- /* The block IDs that the switches support are unfortunately sparse, so keep a
- * mapping table to "block indices" and translate back and forth.
- */
- static const u64 blk_id_map[BLK_IDX_MAX] = {
- [BLK_IDX_L2_POLICING] = BLKID_L2_POLICING,
- [BLK_IDX_VLAN_LOOKUP] = BLKID_VLAN_LOOKUP,
- [BLK_IDX_L2_FORWARDING] = BLKID_L2_FORWARDING,
- [BLK_IDX_MAC_CONFIG] = BLKID_MAC_CONFIG,
- [BLK_IDX_L2_FORWARDING_PARAMS] = BLKID_L2_FORWARDING_PARAMS,
- [BLK_IDX_GENERAL_PARAMS] = BLKID_GENERAL_PARAMS,
- [BLK_IDX_XMII_PARAMS] = BLKID_XMII_PARAMS,
- };
- static void
- sja1105_static_config_pack(void *buf, struct sja1105_static_config *config)
- {
- struct sja1105_table_header header = {0};
- enum sja1105_blk_idx i;
- u8 *p = buf;
- int j;
- sja1105_packing(p, &config->device_id, 31, 0, 4, PACK);
- p += SJA1105_SIZE_DEVICE_ID;
- for (i = 0; i < BLK_IDX_MAX; i++) {
- const struct sja1105_table *table;
- u8 *table_start;
- table = &config->tables[i];
- if (!table->entry_count)
- continue;
- header.block_id = blk_id_map[i];
- header.len = table->entry_count *
- table->ops->packed_entry_size / 4;
- sja1105_table_header_pack_with_crc(p, &header);
- p += SJA1105_SIZE_TABLE_HEADER;
- table_start = p;
- for (j = 0; j < table->entry_count; j++) {
- u8 *entry_ptr = table->entries;
- entry_ptr += j * table->ops->unpacked_entry_size;
- memset(p, 0, table->ops->packed_entry_size);
- table->ops->packing(p, entry_ptr, PACK);
- p += table->ops->packed_entry_size;
- }
- sja1105_table_write_crc(table_start, p);
- p += 4;
- }
- /* Final header:
- * Block ID does not matter
- * Length of 0 marks that header is final
- * CRC will be replaced on-the-fly
- */
- header.block_id = 0;
- header.len = 0;
- header.crc = 0xDEADBEEF;
- memset(p, 0, SJA1105_SIZE_TABLE_HEADER);
- sja1105_table_header_packing(p, &header, PACK);
- }
- static size_t
- sja1105_static_config_get_length(const struct sja1105_static_config *config)
- {
- unsigned int header_count;
- enum sja1105_blk_idx i;
- unsigned int sum;
- /* Ending header */
- header_count = 1;
- sum = SJA1105_SIZE_DEVICE_ID;
- /* Tables (headers and entries) */
- for (i = 0; i < BLK_IDX_MAX; i++) {
- const struct sja1105_table *table;
- table = &config->tables[i];
- if (table->entry_count)
- header_count++;
- sum += table->ops->packed_entry_size * table->entry_count;
- }
- /* Headers have an additional CRC at the end */
- sum += header_count * (SJA1105_SIZE_TABLE_HEADER + 4);
- /* Last header does not have an extra CRC because there is no data */
- sum -= 4;
- return sum;
- }
- /* Compatibility matrices */
- static const struct sja1105_table_ops sja1105et_table_ops[BLK_IDX_MAX] = {
- [BLK_IDX_L2_POLICING] = {
- .packing = sja1105_l2_policing_entry_packing,
- .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
- .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
- .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
- },
- [BLK_IDX_VLAN_LOOKUP] = {
- .packing = sja1105_vlan_lookup_entry_packing,
- .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
- .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
- .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
- },
- [BLK_IDX_L2_FORWARDING] = {
- .packing = sja1105_l2_forwarding_entry_packing,
- .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
- .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
- .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
- },
- [BLK_IDX_MAC_CONFIG] = {
- .packing = sja1105et_mac_config_entry_packing,
- .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
- .packed_entry_size = SJA1105ET_SIZE_MAC_CONFIG_ENTRY,
- .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
- },
- [BLK_IDX_L2_FORWARDING_PARAMS] = {
- .packing = sja1105_l2_forwarding_params_entry_packing,
- .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
- .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
- .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
- },
- [BLK_IDX_GENERAL_PARAMS] = {
- .packing = sja1105et_general_params_entry_packing,
- .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
- .packed_entry_size = SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY,
- .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
- },
- [BLK_IDX_XMII_PARAMS] = {
- .packing = sja1105_xmii_params_entry_packing,
- .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
- .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
- .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
- },
- };
- static const struct sja1105_table_ops sja1105pqrs_table_ops[BLK_IDX_MAX] = {
- [BLK_IDX_L2_POLICING] = {
- .packing = sja1105_l2_policing_entry_packing,
- .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
- .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
- .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
- },
- [BLK_IDX_VLAN_LOOKUP] = {
- .packing = sja1105_vlan_lookup_entry_packing,
- .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
- .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
- .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
- },
- [BLK_IDX_L2_FORWARDING] = {
- .packing = sja1105_l2_forwarding_entry_packing,
- .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
- .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
- .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
- },
- [BLK_IDX_MAC_CONFIG] = {
- .packing = sja1105pqrs_mac_config_entry_packing,
- .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
- .packed_entry_size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY,
- .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
- },
- [BLK_IDX_L2_FORWARDING_PARAMS] = {
- .packing = sja1105_l2_forwarding_params_entry_packing,
- .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
- .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
- .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
- },
- [BLK_IDX_GENERAL_PARAMS] = {
- .packing = sja1105pqrs_general_params_entry_packing,
- .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
- .packed_entry_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY,
- .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
- },
- [BLK_IDX_XMII_PARAMS] = {
- .packing = sja1105_xmii_params_entry_packing,
- .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
- .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
- .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
- },
- };
- static const struct sja1105_table_ops sja1110_table_ops[BLK_IDX_MAX] = {
- [BLK_IDX_L2_POLICING] = {
- .packing = sja1110_l2_policing_entry_packing,
- .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
- .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
- .max_entry_count = SJA1110_MAX_L2_POLICING_COUNT,
- },
- [BLK_IDX_VLAN_LOOKUP] = {
- .packing = sja1110_vlan_lookup_entry_packing,
- .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
- .packed_entry_size = SJA1110_SIZE_VLAN_LOOKUP_ENTRY,
- .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
- },
- [BLK_IDX_L2_FORWARDING] = {
- .packing = sja1110_l2_forwarding_entry_packing,
- .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
- .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
- .max_entry_count = SJA1110_MAX_L2_FORWARDING_COUNT,
- },
- [BLK_IDX_MAC_CONFIG] = {
- .packing = sja1110_mac_config_entry_packing,
- .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
- .packed_entry_size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY,
- .max_entry_count = SJA1110_MAX_MAC_CONFIG_COUNT,
- },
- [BLK_IDX_L2_FORWARDING_PARAMS] = {
- .packing = sja1110_l2_forwarding_params_entry_packing,
- .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
- .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
- .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
- },
- [BLK_IDX_GENERAL_PARAMS] = {
- .packing = sja1110_general_params_entry_packing,
- .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
- .packed_entry_size = SJA1110_SIZE_GENERAL_PARAMS_ENTRY,
- .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
- },
- [BLK_IDX_XMII_PARAMS] = {
- .packing = sja1110_xmii_params_entry_packing,
- .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
- .packed_entry_size = SJA1110_SIZE_XMII_PARAMS_ENTRY,
- .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
- },
- };
- static int sja1105_init_mii_settings(struct sja1105_private *priv)
- {
- struct sja1105_table *table;
- table = &priv->static_config.tables[BLK_IDX_XMII_PARAMS];
- table->entries = calloc(SJA1105_MAX_XMII_PARAMS_COUNT,
- table->ops->unpacked_entry_size);
- if (!table->entries)
- return -ENOMEM;
- /* Table will be populated at runtime */
- table->entry_count = SJA1105_MAX_XMII_PARAMS_COUNT;
- return 0;
- }
- static void sja1105_setup_tagging(struct sja1105_private *priv, int port)
- {
- struct dsa_pdata *pdata = dev_get_uclass_plat(priv->dev);
- struct sja1105_vlan_lookup_entry *vlan;
- int cpu = pdata->cpu_port;
- /* The CPU port is implicitly configured by
- * configuring the front-panel ports
- */
- if (port == cpu)
- return;
- vlan = priv->static_config.tables[BLK_IDX_VLAN_LOOKUP].entries;
- priv->pvid[port] = DSA_8021Q_DIR_TX | DSA_8021Q_PORT(port);
- vlan[port].vmemb_port = BIT(port) | BIT(cpu);
- vlan[port].vlan_bc = BIT(port) | BIT(cpu);
- vlan[port].tag_port = BIT(cpu);
- vlan[port].vlanid = priv->pvid[port];
- vlan[port].type_entry = SJA1110_VLAN_D_TAG;
- }
- static int sja1105_init_vlan(struct sja1105_private *priv)
- {
- struct dsa_pdata *pdata = dev_get_uclass_plat(priv->dev);
- struct sja1105_table *table;
- int port;
- table = &priv->static_config.tables[BLK_IDX_VLAN_LOOKUP];
- table->entries = calloc(pdata->num_ports,
- table->ops->unpacked_entry_size);
- if (!table->entries)
- return -ENOMEM;
- table->entry_count = pdata->num_ports;
- for (port = 0; port < pdata->num_ports; port++)
- sja1105_setup_tagging(priv, port);
- return 0;
- }
- static void
- sja1105_port_allow_traffic(struct sja1105_l2_forwarding_entry *l2_fwd,
- int from, int to)
- {
- l2_fwd[from].bc_domain |= BIT(to);
- l2_fwd[from].reach_port |= BIT(to);
- l2_fwd[from].fl_domain |= BIT(to);
- }
- static int sja1105_init_l2_forwarding(struct sja1105_private *priv)
- {
- struct dsa_pdata *pdata = dev_get_uclass_plat(priv->dev);
- struct sja1105_l2_forwarding_entry *l2fwd;
- struct sja1105_table *table;
- int cpu = pdata->cpu_port;
- int i;
- table = &priv->static_config.tables[BLK_IDX_L2_FORWARDING];
- table->entries = calloc(SJA1105_MAX_L2_FORWARDING_COUNT,
- table->ops->unpacked_entry_size);
- if (!table->entries)
- return -ENOMEM;
- table->entry_count = SJA1105_MAX_L2_FORWARDING_COUNT;
- l2fwd = table->entries;
- /* First 5 entries define the forwarding rules */
- for (i = 0; i < pdata->num_ports; i++) {
- if (i == cpu)
- continue;
- sja1105_port_allow_traffic(l2fwd, i, cpu);
- sja1105_port_allow_traffic(l2fwd, cpu, i);
- }
- /* Next 8 entries define VLAN PCP mapping from ingress to egress.
- * Leave them unpopulated (implicitly 0) but present.
- */
- return 0;
- }
- static int sja1105_init_l2_forwarding_params(struct sja1105_private *priv)
- {
- struct sja1105_l2_forwarding_params_entry default_l2fwd_params = {
- /* Use a single memory partition for all ingress queues */
- .part_spc = { SJA1105_MAX_FRAME_MEMORY, 0, 0, 0, 0, 0, 0, 0 },
- };
- struct sja1105_table *table;
- table = &priv->static_config.tables[BLK_IDX_L2_FORWARDING_PARAMS];
- table->entries = calloc(SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
- table->ops->unpacked_entry_size);
- if (!table->entries)
- return -ENOMEM;
- table->entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT;
- /* This table only has a single entry */
- ((struct sja1105_l2_forwarding_params_entry *)table->entries)[0] =
- default_l2fwd_params;
- return 0;
- }
- static int sja1105_init_general_params(struct sja1105_private *priv)
- {
- struct dsa_pdata *pdata = dev_get_uclass_plat(priv->dev);
- struct sja1105_general_params_entry default_general_params = {
- /* No frame trapping */
- .mac_fltres1 = 0x0,
- .mac_flt1 = 0xffffffffffff,
- .mac_fltres0 = 0x0,
- .mac_flt0 = 0xffffffffffff,
- .host_port = pdata->num_ports,
- /* No mirroring => specify an out-of-range port value */
- .mirr_port = pdata->num_ports,
- /* No link-local trapping => specify an out-of-range port value
- */
- .casc_port = pdata->num_ports,
- /* Force the switch to see all traffic as untagged. */
- .tpid = ETH_P_SJA1105,
- .tpid2 = ETH_P_SJA1105,
- };
- struct sja1105_table *table;
- table = &priv->static_config.tables[BLK_IDX_GENERAL_PARAMS];
- table->entries = calloc(SJA1105_MAX_GENERAL_PARAMS_COUNT,
- table->ops->unpacked_entry_size);
- if (!table->entries)
- return -ENOMEM;
- table->entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT;
- /* This table only has a single entry */
- ((struct sja1105_general_params_entry *)table->entries)[0] =
- default_general_params;
- return 0;
- }
- static void sja1105_setup_policer(struct sja1105_l2_policing_entry *policing,
- int index, int mtu)
- {
- policing[index].sharindx = index;
- policing[index].smax = 65535; /* Burst size in bytes */
- policing[index].rate = SJA1105_RATE_MBPS(1000);
- policing[index].maxlen = mtu;
- policing[index].partition = 0;
- }
- static int sja1105_init_l2_policing(struct sja1105_private *priv)
- {
- struct dsa_pdata *pdata = dev_get_uclass_plat(priv->dev);
- struct sja1105_l2_policing_entry *policing;
- struct sja1105_table *table;
- int cpu = pdata->cpu_port;
- int i, j, k;
- table = &priv->static_config.tables[BLK_IDX_L2_POLICING];
- table->entries = calloc(SJA1105_MAX_L2_POLICING_COUNT,
- table->ops->unpacked_entry_size);
- if (!table->entries)
- return -ENOMEM;
- table->entry_count = SJA1105_MAX_L2_POLICING_COUNT;
- policing = table->entries;
- /* k sweeps through all unicast policers (0-39).
- * bcast sweeps through policers 40-44.
- */
- for (i = 0, k = 0; i < pdata->num_ports; i++) {
- int bcast = (pdata->num_ports * SJA1105_NUM_TC) + i;
- int mtu = VLAN_ETH_FRAME_LEN + ETH_FCS_LEN;
- if (i == cpu)
- mtu += VLAN_HLEN;
- for (j = 0; j < SJA1105_NUM_TC; j++, k++)
- sja1105_setup_policer(policing, k, mtu);
- /* Set up this port's policer for broadcast traffic */
- sja1105_setup_policer(policing, bcast, mtu);
- }
- return 0;
- }
- static int sja1105_init_mac_settings(struct sja1105_private *priv)
- {
- struct sja1105_mac_config_entry default_mac = {
- /* Enable 1 priority queue on egress. */
- .top = {0x1FF, 0, 0, 0, 0, 0, 0},
- .base = {0x0, 0, 0, 0, 0, 0, 0, 0},
- .enabled = {1, 0, 0, 0, 0, 0, 0, 0},
- /* Will be overridden in sja1105_port_enable. */
- .speed = priv->info->port_speed[SJA1105_SPEED_AUTO],
- .egress = true,
- .ingress = true,
- };
- struct dsa_pdata *pdata = dev_get_uclass_plat(priv->dev);
- struct sja1105_mac_config_entry *mac;
- struct sja1105_table *table;
- int port;
- table = &priv->static_config.tables[BLK_IDX_MAC_CONFIG];
- table->entries = calloc(pdata->num_ports,
- table->ops->unpacked_entry_size);
- if (!table->entries)
- return -ENOMEM;
- table->entry_count = pdata->num_ports;
- mac = table->entries;
- for (port = 0; port < pdata->num_ports; port++) {
- mac[port] = default_mac;
- /* Internal VLAN (pvid) to apply to untagged ingress */
- mac[port].vlanid = priv->pvid[port];
- }
- return 0;
- }
- static int sja1105_static_config_init(struct sja1105_private *priv)
- {
- struct sja1105_static_config *config = &priv->static_config;
- const struct sja1105_table_ops *static_ops = priv->info->static_ops;
- u64 device_id = priv->info->device_id;
- enum sja1105_blk_idx i;
- int rc;
- *config = (struct sja1105_static_config) {0};
- /* Transfer static_ops array from priv into per-table ops
- * for handier access
- */
- for (i = 0; i < BLK_IDX_MAX; i++)
- config->tables[i].ops = &static_ops[i];
- config->device_id = device_id;
- /* Build initial static configuration, to be fixed up during runtime */
- rc = sja1105_init_vlan(priv);
- if (rc < 0)
- return rc;
- rc = sja1105_init_mac_settings(priv);
- if (rc < 0)
- return rc;
- rc = sja1105_init_mii_settings(priv);
- if (rc < 0)
- return rc;
- rc = sja1105_init_l2_forwarding(priv);
- if (rc < 0)
- return rc;
- rc = sja1105_init_l2_forwarding_params(priv);
- if (rc < 0)
- return rc;
- rc = sja1105_init_l2_policing(priv);
- if (rc < 0)
- return rc;
- rc = sja1105_init_general_params(priv);
- if (rc < 0)
- return rc;
- return 0;
- }
- static void sja1105_static_config_free(struct sja1105_static_config *config)
- {
- enum sja1105_blk_idx i;
- for (i = 0; i < BLK_IDX_MAX; i++) {
- if (config->tables[i].entry_count) {
- free(config->tables[i].entries);
- config->tables[i].entry_count = 0;
- }
- }
- }
- static void sja1105_cgu_idiv_packing(void *buf, struct sja1105_cgu_idiv *idiv,
- enum packing_op op)
- {
- const int size = 4;
- sja1105_packing(buf, &idiv->clksrc, 28, 24, size, op);
- sja1105_packing(buf, &idiv->autoblock, 11, 11, size, op);
- sja1105_packing(buf, &idiv->idiv, 5, 2, size, op);
- sja1105_packing(buf, &idiv->pd, 0, 0, size, op);
- }
- static int sja1105_cgu_idiv_config(struct sja1105_private *priv, int port,
- bool enabled, int factor)
- {
- const struct sja1105_regs *regs = priv->info->regs;
- u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
- struct sja1105_cgu_idiv idiv;
- if (regs->cgu_idiv[port] == SJA1105_RSV_ADDR)
- return 0;
- if (enabled && factor != 1 && factor != 10)
- return -ERANGE;
- /* Payload for packed_buf */
- idiv.clksrc = 0x0A; /* 25MHz */
- idiv.autoblock = 1; /* Block clk automatically */
- idiv.idiv = factor - 1; /* Divide by 1 or 10 */
- idiv.pd = enabled ? 0 : 1; /* Power down? */
- sja1105_cgu_idiv_packing(packed_buf, &idiv, PACK);
- return sja1105_xfer_buf(priv, SPI_WRITE, regs->cgu_idiv[port],
- packed_buf, SJA1105_SIZE_CGU_CMD);
- }
- static void
- sja1105_cgu_mii_control_packing(void *buf, struct sja1105_cgu_mii_ctrl *cmd,
- enum packing_op op)
- {
- const int size = 4;
- sja1105_packing(buf, &cmd->clksrc, 28, 24, size, op);
- sja1105_packing(buf, &cmd->autoblock, 11, 11, size, op);
- sja1105_packing(buf, &cmd->pd, 0, 0, size, op);
- }
- static int sja1105_cgu_mii_tx_clk_config(struct sja1105_private *priv,
- int port, sja1105_mii_role_t role)
- {
- const struct sja1105_regs *regs = priv->info->regs;
- struct sja1105_cgu_mii_ctrl mii_tx_clk;
- const int mac_clk_sources[] = {
- CLKSRC_MII0_TX_CLK,
- CLKSRC_MII1_TX_CLK,
- CLKSRC_MII2_TX_CLK,
- CLKSRC_MII3_TX_CLK,
- CLKSRC_MII4_TX_CLK,
- };
- const int phy_clk_sources[] = {
- CLKSRC_IDIV0,
- CLKSRC_IDIV1,
- CLKSRC_IDIV2,
- CLKSRC_IDIV3,
- CLKSRC_IDIV4,
- };
- u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
- int clksrc;
- if (regs->mii_tx_clk[port] == SJA1105_RSV_ADDR)
- return 0;
- if (role == XMII_MAC)
- clksrc = mac_clk_sources[port];
- else
- clksrc = phy_clk_sources[port];
- /* Payload for packed_buf */
- mii_tx_clk.clksrc = clksrc;
- mii_tx_clk.autoblock = 1; /* Autoblock clk while changing clksrc */
- mii_tx_clk.pd = 0; /* Power Down off => enabled */
- sja1105_cgu_mii_control_packing(packed_buf, &mii_tx_clk, PACK);
- return sja1105_xfer_buf(priv, SPI_WRITE, regs->mii_tx_clk[port],
- packed_buf, SJA1105_SIZE_CGU_CMD);
- }
- static int
- sja1105_cgu_mii_rx_clk_config(struct sja1105_private *priv, int port)
- {
- const struct sja1105_regs *regs = priv->info->regs;
- u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
- struct sja1105_cgu_mii_ctrl mii_rx_clk;
- const int clk_sources[] = {
- CLKSRC_MII0_RX_CLK,
- CLKSRC_MII1_RX_CLK,
- CLKSRC_MII2_RX_CLK,
- CLKSRC_MII3_RX_CLK,
- CLKSRC_MII4_RX_CLK,
- };
- if (regs->mii_rx_clk[port] == SJA1105_RSV_ADDR)
- return 0;
- /* Payload for packed_buf */
- mii_rx_clk.clksrc = clk_sources[port];
- mii_rx_clk.autoblock = 1; /* Autoblock clk while changing clksrc */
- mii_rx_clk.pd = 0; /* Power Down off => enabled */
- sja1105_cgu_mii_control_packing(packed_buf, &mii_rx_clk, PACK);
- return sja1105_xfer_buf(priv, SPI_WRITE, regs->mii_rx_clk[port],
- packed_buf, SJA1105_SIZE_CGU_CMD);
- }
- static int
- sja1105_cgu_mii_ext_tx_clk_config(struct sja1105_private *priv, int port)
- {
- const struct sja1105_regs *regs = priv->info->regs;
- struct sja1105_cgu_mii_ctrl mii_ext_tx_clk;
- u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
- const int clk_sources[] = {
- CLKSRC_IDIV0,
- CLKSRC_IDIV1,
- CLKSRC_IDIV2,
- CLKSRC_IDIV3,
- CLKSRC_IDIV4,
- };
- if (regs->mii_ext_tx_clk[port] == SJA1105_RSV_ADDR)
- return 0;
- /* Payload for packed_buf */
- mii_ext_tx_clk.clksrc = clk_sources[port];
- mii_ext_tx_clk.autoblock = 1; /* Autoblock clk while changing clksrc */
- mii_ext_tx_clk.pd = 0; /* Power Down off => enabled */
- sja1105_cgu_mii_control_packing(packed_buf, &mii_ext_tx_clk, PACK);
- return sja1105_xfer_buf(priv, SPI_WRITE, regs->mii_ext_tx_clk[port],
- packed_buf, SJA1105_SIZE_CGU_CMD);
- }
- static int
- sja1105_cgu_mii_ext_rx_clk_config(struct sja1105_private *priv, int port)
- {
- const struct sja1105_regs *regs = priv->info->regs;
- struct sja1105_cgu_mii_ctrl mii_ext_rx_clk;
- u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
- const int clk_sources[] = {
- CLKSRC_IDIV0,
- CLKSRC_IDIV1,
- CLKSRC_IDIV2,
- CLKSRC_IDIV3,
- CLKSRC_IDIV4,
- };
- if (regs->mii_ext_rx_clk[port] == SJA1105_RSV_ADDR)
- return 0;
- /* Payload for packed_buf */
- mii_ext_rx_clk.clksrc = clk_sources[port];
- mii_ext_rx_clk.autoblock = 1; /* Autoblock clk while changing clksrc */
- mii_ext_rx_clk.pd = 0; /* Power Down off => enabled */
- sja1105_cgu_mii_control_packing(packed_buf, &mii_ext_rx_clk, PACK);
- return sja1105_xfer_buf(priv, SPI_WRITE, regs->mii_ext_rx_clk[port],
- packed_buf, SJA1105_SIZE_CGU_CMD);
- }
- static int sja1105_mii_clocking_setup(struct sja1105_private *priv, int port,
- sja1105_mii_role_t role)
- {
- int rc;
- rc = sja1105_cgu_idiv_config(priv, port, (role == XMII_PHY), 1);
- if (rc < 0)
- return rc;
- rc = sja1105_cgu_mii_tx_clk_config(priv, port, role);
- if (rc < 0)
- return rc;
- rc = sja1105_cgu_mii_rx_clk_config(priv, port);
- if (rc < 0)
- return rc;
- if (role == XMII_PHY) {
- rc = sja1105_cgu_mii_ext_tx_clk_config(priv, port);
- if (rc < 0)
- return rc;
- rc = sja1105_cgu_mii_ext_rx_clk_config(priv, port);
- if (rc < 0)
- return rc;
- }
- return 0;
- }
- static void
- sja1105_cgu_pll_control_packing(void *buf, struct sja1105_cgu_pll_ctrl *cmd,
- enum packing_op op)
- {
- const int size = 4;
- sja1105_packing(buf, &cmd->pllclksrc, 28, 24, size, op);
- sja1105_packing(buf, &cmd->msel, 23, 16, size, op);
- sja1105_packing(buf, &cmd->autoblock, 11, 11, size, op);
- sja1105_packing(buf, &cmd->psel, 9, 8, size, op);
- sja1105_packing(buf, &cmd->direct, 7, 7, size, op);
- sja1105_packing(buf, &cmd->fbsel, 6, 6, size, op);
- sja1105_packing(buf, &cmd->bypass, 1, 1, size, op);
- sja1105_packing(buf, &cmd->pd, 0, 0, size, op);
- }
- static int sja1105_cgu_rgmii_tx_clk_config(struct sja1105_private *priv,
- int port, u64 speed)
- {
- const struct sja1105_regs *regs = priv->info->regs;
- struct sja1105_cgu_mii_ctrl txc;
- u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
- int clksrc;
- if (regs->rgmii_tx_clk[port] == SJA1105_RSV_ADDR)
- return 0;
- if (speed == priv->info->port_speed[SJA1105_SPEED_1000MBPS]) {
- clksrc = CLKSRC_PLL0;
- } else {
- int clk_sources[] = {CLKSRC_IDIV0, CLKSRC_IDIV1, CLKSRC_IDIV2,
- CLKSRC_IDIV3, CLKSRC_IDIV4};
- clksrc = clk_sources[port];
- }
- /* RGMII: 125MHz for 1000, 25MHz for 100, 2.5MHz for 10 */
- txc.clksrc = clksrc;
- /* Autoblock clk while changing clksrc */
- txc.autoblock = 1;
- /* Power Down off => enabled */
- txc.pd = 0;
- sja1105_cgu_mii_control_packing(packed_buf, &txc, PACK);
- return sja1105_xfer_buf(priv, SPI_WRITE, regs->rgmii_tx_clk[port],
- packed_buf, SJA1105_SIZE_CGU_CMD);
- }
- /* AGU */
- static void
- sja1105_cfg_pad_mii_packing(void *buf, struct sja1105_cfg_pad_mii *cmd,
- enum packing_op op)
- {
- const int size = 4;
- sja1105_packing(buf, &cmd->d32_os, 28, 27, size, op);
- sja1105_packing(buf, &cmd->d32_ih, 26, 26, size, op);
- sja1105_packing(buf, &cmd->d32_ipud, 25, 24, size, op);
- sja1105_packing(buf, &cmd->d10_os, 20, 19, size, op);
- sja1105_packing(buf, &cmd->d10_ih, 18, 18, size, op);
- sja1105_packing(buf, &cmd->d10_ipud, 17, 16, size, op);
- sja1105_packing(buf, &cmd->ctrl_os, 12, 11, size, op);
- sja1105_packing(buf, &cmd->ctrl_ih, 10, 10, size, op);
- sja1105_packing(buf, &cmd->ctrl_ipud, 9, 8, size, op);
- sja1105_packing(buf, &cmd->clk_os, 4, 3, size, op);
- sja1105_packing(buf, &cmd->clk_ih, 2, 2, size, op);
- sja1105_packing(buf, &cmd->clk_ipud, 1, 0, size, op);
- }
- static void
- sja1110_cfg_pad_mii_id_packing(void *buf, struct sja1105_cfg_pad_mii_id *cmd,
- enum packing_op op)
- {
- const int size = SJA1105_SIZE_CGU_CMD;
- u64 range = 4;
- /* Fields RXC_RANGE and TXC_RANGE select the input frequency range:
- * 0 = 2.5MHz
- * 1 = 25MHz
- * 2 = 50MHz
- * 3 = 125MHz
- * 4 = Automatically determined by port speed.
- * There's no point in defining a structure different than the one for
- * SJA1105, so just hardcode the frequency range to automatic, just as
- * before.
- */
- sja1105_packing(buf, &cmd->rxc_stable_ovr, 26, 26, size, op);
- sja1105_packing(buf, &cmd->rxc_delay, 25, 21, size, op);
- sja1105_packing(buf, &range, 20, 18, size, op);
- sja1105_packing(buf, &cmd->rxc_bypass, 17, 17, size, op);
- sja1105_packing(buf, &cmd->rxc_pd, 16, 16, size, op);
- sja1105_packing(buf, &cmd->txc_stable_ovr, 10, 10, size, op);
- sja1105_packing(buf, &cmd->txc_delay, 9, 5, size, op);
- sja1105_packing(buf, &range, 4, 2, size, op);
- sja1105_packing(buf, &cmd->txc_bypass, 1, 1, size, op);
- sja1105_packing(buf, &cmd->txc_pd, 0, 0, size, op);
- }
- static int sja1105_rgmii_cfg_pad_tx_config(struct sja1105_private *priv,
- int port)
- {
- const struct sja1105_regs *regs = priv->info->regs;
- struct sja1105_cfg_pad_mii pad_mii_tx = {0};
- u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
- if (regs->pad_mii_tx[port] == SJA1105_RSV_ADDR)
- return 0;
- /* Payload */
- pad_mii_tx.d32_os = 3; /* TXD[3:2] output stage: */
- /* high noise/high speed */
- pad_mii_tx.d10_os = 3; /* TXD[1:0] output stage: */
- /* high noise/high speed */
- pad_mii_tx.d32_ipud = 2; /* TXD[3:2] input stage: */
- /* plain input (default) */
- pad_mii_tx.d10_ipud = 2; /* TXD[1:0] input stage: */
- /* plain input (default) */
- pad_mii_tx.ctrl_os = 3; /* TX_CTL / TX_ER output stage */
- pad_mii_tx.ctrl_ipud = 2; /* TX_CTL / TX_ER input stage (default) */
- pad_mii_tx.clk_os = 3; /* TX_CLK output stage */
- pad_mii_tx.clk_ih = 0; /* TX_CLK input hysteresis (default) */
- pad_mii_tx.clk_ipud = 2; /* TX_CLK input stage (default) */
- sja1105_cfg_pad_mii_packing(packed_buf, &pad_mii_tx, PACK);
- return sja1105_xfer_buf(priv, SPI_WRITE, regs->pad_mii_tx[port],
- packed_buf, SJA1105_SIZE_CGU_CMD);
- }
- static int sja1105_cfg_pad_rx_config(struct sja1105_private *priv, int port)
- {
- const struct sja1105_regs *regs = priv->info->regs;
- struct sja1105_cfg_pad_mii pad_mii_rx = {0};
- u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
- if (regs->pad_mii_rx[port] == SJA1105_RSV_ADDR)
- return 0;
- /* Payload */
- pad_mii_rx.d32_ih = 0; /* RXD[3:2] input stage hysteresis: */
- /* non-Schmitt (default) */
- pad_mii_rx.d32_ipud = 2; /* RXD[3:2] input weak pull-up/down */
- /* plain input (default) */
- pad_mii_rx.d10_ih = 0; /* RXD[1:0] input stage hysteresis: */
- /* non-Schmitt (default) */
- pad_mii_rx.d10_ipud = 2; /* RXD[1:0] input weak pull-up/down */
- /* plain input (default) */
- pad_mii_rx.ctrl_ih = 0; /* RX_DV/CRS_DV/RX_CTL and RX_ER */
- /* input stage hysteresis: */
- /* non-Schmitt (default) */
- pad_mii_rx.ctrl_ipud = 3; /* RX_DV/CRS_DV/RX_CTL and RX_ER */
- /* input stage weak pull-up/down: */
- /* pull-down */
- pad_mii_rx.clk_os = 2; /* RX_CLK/RXC output stage: */
- /* medium noise/fast speed (default) */
- pad_mii_rx.clk_ih = 0; /* RX_CLK/RXC input hysteresis: */
- /* non-Schmitt (default) */
- pad_mii_rx.clk_ipud = 2; /* RX_CLK/RXC input pull-up/down: */
- /* plain input (default) */
- sja1105_cfg_pad_mii_packing(packed_buf, &pad_mii_rx, PACK);
- return sja1105_xfer_buf(priv, SPI_WRITE, regs->pad_mii_rx[port],
- packed_buf, SJA1105_SIZE_CGU_CMD);
- }
- static void
- sja1105_cfg_pad_mii_id_packing(void *buf, struct sja1105_cfg_pad_mii_id *cmd,
- enum packing_op op)
- {
- const int size = SJA1105_SIZE_CGU_CMD;
- sja1105_packing(buf, &cmd->rxc_stable_ovr, 15, 15, size, op);
- sja1105_packing(buf, &cmd->rxc_delay, 14, 10, size, op);
- sja1105_packing(buf, &cmd->rxc_bypass, 9, 9, size, op);
- sja1105_packing(buf, &cmd->rxc_pd, 8, 8, size, op);
- sja1105_packing(buf, &cmd->txc_stable_ovr, 7, 7, size, op);
- sja1105_packing(buf, &cmd->txc_delay, 6, 2, size, op);
- sja1105_packing(buf, &cmd->txc_bypass, 1, 1, size, op);
- sja1105_packing(buf, &cmd->txc_pd, 0, 0, size, op);
- }
- /* Valid range in degrees is an integer between 73.8 and 101.7 */
- static u64 sja1105_rgmii_delay(u64 phase)
- {
- /* UM11040.pdf: The delay in degree phase is 73.8 + delay_tune * 0.9.
- * To avoid floating point operations we'll multiply by 10
- * and get 1 decimal point precision.
- */
- phase *= 10;
- return (phase - 738) / 9;
- }
- static int sja1105pqrs_setup_rgmii_delay(struct sja1105_private *priv, int port)
- {
- const struct sja1105_regs *regs = priv->info->regs;
- struct sja1105_cfg_pad_mii_id pad_mii_id = {0};
- u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
- int rc;
- if (priv->rgmii_rx_delay[port])
- pad_mii_id.rxc_delay = sja1105_rgmii_delay(90);
- if (priv->rgmii_tx_delay[port])
- pad_mii_id.txc_delay = sja1105_rgmii_delay(90);
- /* Stage 1: Turn the RGMII delay lines off. */
- pad_mii_id.rxc_bypass = 1;
- pad_mii_id.rxc_pd = 1;
- pad_mii_id.txc_bypass = 1;
- pad_mii_id.txc_pd = 1;
- sja1105_cfg_pad_mii_id_packing(packed_buf, &pad_mii_id, PACK);
- rc = sja1105_xfer_buf(priv, SPI_WRITE, regs->pad_mii_id[port],
- packed_buf, SJA1105_SIZE_CGU_CMD);
- if (rc < 0)
- return rc;
- /* Stage 2: Turn the RGMII delay lines on. */
- if (priv->rgmii_rx_delay[port]) {
- pad_mii_id.rxc_bypass = 0;
- pad_mii_id.rxc_pd = 0;
- }
- if (priv->rgmii_tx_delay[port]) {
- pad_mii_id.txc_bypass = 0;
- pad_mii_id.txc_pd = 0;
- }
- sja1105_cfg_pad_mii_id_packing(packed_buf, &pad_mii_id, PACK);
- return sja1105_xfer_buf(priv, SPI_WRITE, regs->pad_mii_id[port],
- packed_buf, SJA1105_SIZE_CGU_CMD);
- }
- static int sja1110_setup_rgmii_delay(struct sja1105_private *priv, int port)
- {
- const struct sja1105_regs *regs = priv->info->regs;
- struct sja1105_cfg_pad_mii_id pad_mii_id = {0};
- u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
- pad_mii_id.rxc_pd = 1;
- pad_mii_id.txc_pd = 1;
- if (priv->rgmii_rx_delay[port]) {
- pad_mii_id.rxc_delay = sja1105_rgmii_delay(90);
- /* The "BYPASS" bit in SJA1110 is actually a "don't bypass" */
- pad_mii_id.rxc_bypass = 1;
- pad_mii_id.rxc_pd = 0;
- }
- if (priv->rgmii_tx_delay[port]) {
- pad_mii_id.txc_delay = sja1105_rgmii_delay(90);
- pad_mii_id.txc_bypass = 1;
- pad_mii_id.txc_pd = 0;
- }
- sja1110_cfg_pad_mii_id_packing(packed_buf, &pad_mii_id, PACK);
- return sja1105_xfer_buf(priv, SPI_WRITE, regs->pad_mii_id[port],
- packed_buf, SJA1105_SIZE_CGU_CMD);
- }
- static int sja1105_rgmii_clocking_setup(struct sja1105_private *priv, int port,
- sja1105_mii_role_t role)
- {
- struct sja1105_mac_config_entry *mac;
- struct udevice *dev = priv->dev;
- u64 speed;
- int rc;
- mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries;
- speed = mac[port].speed;
- if (speed == priv->info->port_speed[SJA1105_SPEED_1000MBPS]) {
- /* 1000Mbps, IDIV disabled (125 MHz) */
- rc = sja1105_cgu_idiv_config(priv, port, false, 1);
- } else if (speed == priv->info->port_speed[SJA1105_SPEED_100MBPS]) {
- /* 100Mbps, IDIV enabled, divide by 1 (25 MHz) */
- rc = sja1105_cgu_idiv_config(priv, port, true, 1);
- } else if (speed == priv->info->port_speed[SJA1105_SPEED_10MBPS]) {
- /* 10Mbps, IDIV enabled, divide by 10 (2.5 MHz) */
- rc = sja1105_cgu_idiv_config(priv, port, true, 10);
- } else if (speed == priv->info->port_speed[SJA1105_SPEED_AUTO]) {
- /* Skip CGU configuration if there is no speed available
- * (e.g. link is not established yet)
- */
- dev_dbg(dev, "Speed not available, skipping CGU config\n");
- return 0;
- } else {
- rc = -EINVAL;
- }
- if (rc < 0) {
- dev_err(dev, "Failed to configure idiv\n");
- return rc;
- }
- rc = sja1105_cgu_rgmii_tx_clk_config(priv, port, speed);
- if (rc < 0) {
- dev_err(dev, "Failed to configure RGMII Tx clock\n");
- return rc;
- }
- rc = sja1105_rgmii_cfg_pad_tx_config(priv, port);
- if (rc < 0) {
- dev_err(dev, "Failed to configure Tx pad registers\n");
- return rc;
- }
- if (!priv->info->setup_rgmii_delay)
- return 0;
- return priv->info->setup_rgmii_delay(priv, port);
- }
- static int sja1105_cgu_rmii_ref_clk_config(struct sja1105_private *priv,
- int port)
- {
- const struct sja1105_regs *regs = priv->info->regs;
- u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
- struct sja1105_cgu_mii_ctrl ref_clk;
- const int clk_sources[] = {
- CLKSRC_MII0_TX_CLK,
- CLKSRC_MII1_TX_CLK,
- CLKSRC_MII2_TX_CLK,
- CLKSRC_MII3_TX_CLK,
- CLKSRC_MII4_TX_CLK,
- };
- if (regs->rmii_ref_clk[port] == SJA1105_RSV_ADDR)
- return 0;
- /* Payload for packed_buf */
- ref_clk.clksrc = clk_sources[port];
- ref_clk.autoblock = 1; /* Autoblock clk while changing clksrc */
- ref_clk.pd = 0; /* Power Down off => enabled */
- sja1105_cgu_mii_control_packing(packed_buf, &ref_clk, PACK);
- return sja1105_xfer_buf(priv, SPI_WRITE, regs->rmii_ref_clk[port],
- packed_buf, SJA1105_SIZE_CGU_CMD);
- }
- static int
- sja1105_cgu_rmii_ext_tx_clk_config(struct sja1105_private *priv, int port)
- {
- const struct sja1105_regs *regs = priv->info->regs;
- struct sja1105_cgu_mii_ctrl ext_tx_clk;
- u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
- if (regs->rmii_ext_tx_clk[port] == SJA1105_RSV_ADDR)
- return 0;
- /* Payload for packed_buf */
- ext_tx_clk.clksrc = CLKSRC_PLL1;
- ext_tx_clk.autoblock = 1; /* Autoblock clk while changing clksrc */
- ext_tx_clk.pd = 0; /* Power Down off => enabled */
- sja1105_cgu_mii_control_packing(packed_buf, &ext_tx_clk, PACK);
- return sja1105_xfer_buf(priv, SPI_WRITE, regs->rmii_ext_tx_clk[port],
- packed_buf, SJA1105_SIZE_CGU_CMD);
- }
- static int sja1105_cgu_rmii_pll_config(struct sja1105_private *priv)
- {
- const struct sja1105_regs *regs = priv->info->regs;
- u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
- struct sja1105_cgu_pll_ctrl pll = {0};
- int rc;
- if (regs->rmii_pll1 == SJA1105_RSV_ADDR)
- return 0;
- /* Step 1: PLL1 setup for 50Mhz */
- pll.pllclksrc = 0xA;
- pll.msel = 0x1;
- pll.autoblock = 0x1;
- pll.psel = 0x1;
- pll.direct = 0x0;
- pll.fbsel = 0x1;
- pll.bypass = 0x0;
- pll.pd = 0x1;
- sja1105_cgu_pll_control_packing(packed_buf, &pll, PACK);
- rc = sja1105_xfer_buf(priv, SPI_WRITE, regs->rmii_pll1, packed_buf,
- SJA1105_SIZE_CGU_CMD);
- if (rc < 0)
- return rc;
- /* Step 2: Enable PLL1 */
- pll.pd = 0x0;
- sja1105_cgu_pll_control_packing(packed_buf, &pll, PACK);
- rc = sja1105_xfer_buf(priv, SPI_WRITE, regs->rmii_pll1, packed_buf,
- SJA1105_SIZE_CGU_CMD);
- return rc;
- }
- static int sja1105_rmii_clocking_setup(struct sja1105_private *priv, int port,
- sja1105_mii_role_t role)
- {
- int rc;
- /* AH1601.pdf chapter 2.5.1. Sources */
- if (role == XMII_MAC) {
- /* Configure and enable PLL1 for 50Mhz output */
- rc = sja1105_cgu_rmii_pll_config(priv);
- if (rc < 0)
- return rc;
- }
- /* Disable IDIV for this port */
- rc = sja1105_cgu_idiv_config(priv, port, false, 1);
- if (rc < 0)
- return rc;
- /* Source to sink mappings */
- rc = sja1105_cgu_rmii_ref_clk_config(priv, port);
- if (rc < 0)
- return rc;
- if (role == XMII_MAC) {
- rc = sja1105_cgu_rmii_ext_tx_clk_config(priv, port);
- if (rc < 0)
- return rc;
- }
- return 0;
- }
- static int sja1105_pcs_read(struct sja1105_private *priv, int addr,
- int devad, int regnum)
- {
- return priv->mdio_pcs->read(priv->mdio_pcs, addr, devad, regnum);
- }
- static int sja1105_pcs_write(struct sja1105_private *priv, int addr,
- int devad, int regnum, u16 val)
- {
- return priv->mdio_pcs->write(priv->mdio_pcs, addr, devad, regnum, val);
- }
- /* In NXP SJA1105, the PCS is integrated with a PMA that has the TX lane
- * polarity inverted by default (PLUS is MINUS, MINUS is PLUS). To obtain
- * normal non-inverted behavior, the TX lane polarity must be inverted in the
- * PCS, via the DIGITAL_CONTROL_2 register.
- */
- static int sja1105_pma_config(struct sja1105_private *priv, int port)
- {
- return sja1105_pcs_write(priv, port, MDIO_MMD_VEND2,
- DW_VR_MII_DIG_CTRL2,
- DW_VR_MII_DIG_CTRL2_TX_POL_INV);
- }
- static int sja1110_pma_config(struct sja1105_private *priv, int port)
- {
- u16 txpll_fbdiv = 0x19, txpll_refdiv = 0x1;
- u16 rxpll_fbdiv = 0x19, rxpll_refdiv = 0x1;
- u16 rx_cdr_ctle = 0x212a;
- u16 val;
- int rc;
- /* Program TX PLL feedback divider and reference divider settings for
- * correct oscillation frequency.
- */
- rc = sja1105_pcs_write(priv, port, MDIO_MMD_VEND2, SJA1110_TXPLL_CTRL0,
- SJA1110_TXPLL_FBDIV(txpll_fbdiv));
- if (rc < 0)
- return rc;
- rc = sja1105_pcs_write(priv, port, MDIO_MMD_VEND2, SJA1110_TXPLL_CTRL1,
- SJA1110_TXPLL_REFDIV(txpll_refdiv));
- if (rc < 0)
- return rc;
- /* Program transmitter amplitude and disable amplitude trimming */
- rc = sja1105_pcs_write(priv, port, MDIO_MMD_VEND2,
- SJA1110_LANE_DRIVER1_0, SJA1110_TXDRV(0x5));
- if (rc < 0)
- return rc;
- val = SJA1110_TXDRVTRIM_LSB(0xffffffull);
- rc = sja1105_pcs_write(priv, port, MDIO_MMD_VEND2,
- SJA1110_LANE_DRIVER2_0, val);
- if (rc < 0)
- return rc;
- val = SJA1110_TXDRVTRIM_MSB(0xffffffull) | SJA1110_LANE_DRIVER2_1_RSV;
- rc = sja1105_pcs_write(priv, port, MDIO_MMD_VEND2,
- SJA1110_LANE_DRIVER2_1, val);
- if (rc < 0)
- return rc;
- /* Enable input and output resistor terminations for low BER. */
- val = SJA1110_ACCOUPLE_RXVCM_EN | SJA1110_CDR_GAIN |
- SJA1110_RXRTRIM(4) | SJA1110_RXTEN | SJA1110_TXPLL_BWSEL |
- SJA1110_TXRTRIM(3) | SJA1110_TXTEN;
- rc = sja1105_pcs_write(priv, port, MDIO_MMD_VEND2, SJA1110_LANE_TRIM,
- val);
- if (rc < 0)
- return rc;
- /* Select PCS as transmitter data source. */
- rc = sja1105_pcs_write(priv, port, MDIO_MMD_VEND2,
- SJA1110_LANE_DATAPATH_1, 0);
- if (rc < 0)
- return rc;
- /* Program RX PLL feedback divider and reference divider for correct
- * oscillation frequency.
- */
- rc = sja1105_pcs_write(priv, port, MDIO_MMD_VEND2, SJA1110_RXPLL_CTRL0,
- SJA1110_RXPLL_FBDIV(rxpll_fbdiv));
- if (rc < 0)
- return rc;
- rc = sja1105_pcs_write(priv, port, MDIO_MMD_VEND2, SJA1110_RXPLL_CTRL1,
- SJA1110_RXPLL_REFDIV(rxpll_refdiv));
- if (rc < 0)
- return rc;
- /* Program threshold for receiver signal detector.
- * Enable control of RXPLL by receiver signal detector to disable RXPLL
- * when an input signal is not present.
- */
- rc = sja1105_pcs_write(priv, port, MDIO_MMD_VEND2,
- SJA1110_RX_DATA_DETECT, 0x0005);
- if (rc < 0)
- return rc;
- /* Enable TX and RX PLLs and circuits.
- * Release reset of PMA to enable data flow to/from PCS.
- */
- rc = sja1105_pcs_read(priv, port, MDIO_MMD_VEND2,
- SJA1110_POWERDOWN_ENABLE);
- if (rc < 0)
- return rc;
- val = rc & ~(SJA1110_TXPLL_PD | SJA1110_TXPD | SJA1110_RXCH_PD |
- SJA1110_RXBIAS_PD | SJA1110_RESET_SER_EN |
- SJA1110_RESET_SER | SJA1110_RESET_DES);
- val |= SJA1110_RXPKDETEN | SJA1110_RCVEN;
- rc = sja1105_pcs_write(priv, port, MDIO_MMD_VEND2,
- SJA1110_POWERDOWN_ENABLE, val);
- if (rc < 0)
- return rc;
- /* Program continuous-time linear equalizer (CTLE) settings. */
- rc = sja1105_pcs_write(priv, port, MDIO_MMD_VEND2, SJA1110_RX_CDR_CTLE,
- rx_cdr_ctle);
- if (rc < 0)
- return rc;
- return 0;
- }
- static int sja1105_xpcs_config_aneg_c37_sgmii(struct sja1105_private *priv,
- int port)
- {
- int rc;
- rc = sja1105_pcs_read(priv, port, MDIO_MMD_VEND2, MDIO_CTRL1);
- if (rc < 0)
- return rc;
- rc &= ~MDIO_AN_CTRL1_ENABLE;
- rc = sja1105_pcs_write(priv, port, MDIO_MMD_VEND2, MDIO_CTRL1,
- rc);
- if (rc < 0)
- return rc;
- rc = sja1105_pcs_read(priv, port, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL);
- if (rc < 0)
- return rc;
- rc &= ~(DW_VR_MII_PCS_MODE_MASK | DW_VR_MII_TX_CONFIG_MASK);
- rc |= (DW_VR_MII_PCS_MODE_C37_SGMII <<
- DW_VR_MII_AN_CTRL_PCS_MODE_SHIFT &
- DW_VR_MII_PCS_MODE_MASK);
- rc |= (DW_VR_MII_TX_CONFIG_MAC_SIDE_SGMII <<
- DW_VR_MII_AN_CTRL_TX_CONFIG_SHIFT &
- DW_VR_MII_TX_CONFIG_MASK);
- rc = sja1105_pcs_write(priv, port, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL,
- rc);
- if (rc < 0)
- return rc;
- rc = sja1105_pcs_read(priv, port, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1);
- if (rc < 0)
- return rc;
- if (priv->xpcs_cfg[port].inband_an)
- rc |= DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
- else
- rc &= ~DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
- rc = sja1105_pcs_write(priv, port, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1,
- rc);
- if (rc < 0)
- return rc;
- rc = sja1105_pcs_read(priv, port, MDIO_MMD_VEND2, MDIO_CTRL1);
- if (rc < 0)
- return rc;
- if (priv->xpcs_cfg[port].inband_an)
- rc |= MDIO_AN_CTRL1_ENABLE;
- else
- rc &= ~MDIO_AN_CTRL1_ENABLE;
- return sja1105_pcs_write(priv, port, MDIO_MMD_VEND2, MDIO_CTRL1, rc);
- }
- static int sja1105_xpcs_link_up_sgmii(struct sja1105_private *priv, int port)
- {
- int val = BMCR_FULLDPLX;
- if (priv->xpcs_cfg[port].inband_an)
- return 0;
- switch (priv->xpcs_cfg[port].speed) {
- case SPEED_1000:
- val = BMCR_SPEED1000;
- break;
- case SPEED_100:
- val = BMCR_SPEED100;
- break;
- case SPEED_10:
- val = BMCR_SPEED10;
- break;
- default:
- dev_err(priv->dev, "Invalid PCS speed %d\n",
- priv->xpcs_cfg[port].speed);
- return -EINVAL;
- }
- return sja1105_pcs_write(priv, port, MDIO_MMD_VEND2, MDIO_CTRL1, val);
- }
- static int sja1105_sgmii_setup(struct sja1105_private *priv, int port)
- {
- int rc;
- rc = sja1105_xpcs_config_aneg_c37_sgmii(priv, port);
- if (rc)
- return rc;
- rc = sja1105_xpcs_link_up_sgmii(priv, port);
- if (rc)
- return rc;
- return priv->info->pma_config(priv, port);
- }
- static int sja1105_clocking_setup_port(struct sja1105_private *priv, int port)
- {
- struct sja1105_xmii_params_entry *mii;
- sja1105_phy_interface_t phy_mode;
- sja1105_mii_role_t role;
- int rc;
- mii = priv->static_config.tables[BLK_IDX_XMII_PARAMS].entries;
- /* RGMII etc */
- phy_mode = mii->xmii_mode[port];
- /* MAC or PHY, for applicable types (not RGMII) */
- role = mii->phy_mac[port];
- switch (phy_mode) {
- case XMII_MODE_MII:
- rc = sja1105_mii_clocking_setup(priv, port, role);
- break;
- case XMII_MODE_RMII:
- rc = sja1105_rmii_clocking_setup(priv, port, role);
- break;
- case XMII_MODE_RGMII:
- rc = sja1105_rgmii_clocking_setup(priv, port, role);
- break;
- case XMII_MODE_SGMII:
- rc = sja1105_sgmii_setup(priv, port);
- break;
- default:
- return -EINVAL;
- }
- if (rc)
- return rc;
- /* Internally pull down the RX_DV/CRS_DV/RX_CTL and RX_ER inputs */
- return sja1105_cfg_pad_rx_config(priv, port);
- }
- static int sja1105_clocking_setup(struct sja1105_private *priv)
- {
- struct dsa_pdata *pdata = dev_get_uclass_plat(priv->dev);
- int port, rc;
- for (port = 0; port < pdata->num_ports; port++) {
- rc = sja1105_clocking_setup_port(priv, port);
- if (rc < 0)
- return rc;
- }
- return 0;
- }
- static int sja1105_pcs_mdio_read(struct mii_dev *bus, int phy, int mmd, int reg)
- {
- u8 packed_buf[SJA1105_SIZE_MDIO_CMD] = {0};
- struct sja1105_private *priv = bus->priv;
- const int size = SJA1105_SIZE_MDIO_CMD;
- u64 addr, tmp;
- int rc;
- if (mmd == MDIO_DEVAD_NONE)
- return -ENODEV;
- if (!priv->info->supports_sgmii[phy])
- return -ENODEV;
- addr = (mmd << 16) | (reg & GENMASK(15, 0));
- if (mmd != MDIO_MMD_VEND1 && mmd != MDIO_MMD_VEND2)
- return 0xffff;
- rc = sja1105_xfer_buf(priv, SPI_READ, addr, packed_buf, size);
- if (rc < 0)
- return rc;
- sja1105_packing(packed_buf, &tmp, 31, 0, size, UNPACK);
- return tmp & 0xffff;
- }
- static int sja1105_pcs_mdio_write(struct mii_dev *bus, int phy, int mmd,
- int reg, u16 val)
- {
- u8 packed_buf[SJA1105_SIZE_MDIO_CMD] = {0};
- struct sja1105_private *priv = bus->priv;
- const int size = SJA1105_SIZE_MDIO_CMD;
- u64 addr, tmp;
- if (mmd == MDIO_DEVAD_NONE)
- return -ENODEV;
- if (!priv->info->supports_sgmii[phy])
- return -ENODEV;
- addr = (mmd << 16) | (reg & GENMASK(15, 0));
- tmp = val;
- if (mmd != MDIO_MMD_VEND1 && mmd != MDIO_MMD_VEND2)
- return -ENODEV;
- sja1105_packing(packed_buf, &tmp, 31, 0, size, PACK);
- return sja1105_xfer_buf(priv, SPI_WRITE, addr, packed_buf, size);
- }
- static int sja1110_pcs_mdio_read(struct mii_dev *bus, int phy, int mmd, int reg)
- {
- struct sja1105_private *priv = bus->priv;
- const struct sja1105_regs *regs = priv->info->regs;
- u8 packed_buf[SJA1105_SIZE_MDIO_CMD] = {0};
- const int size = SJA1105_SIZE_MDIO_CMD;
- int offset, bank;
- u64 addr, tmp;
- int rc;
- if (mmd == MDIO_DEVAD_NONE)
- return -ENODEV;
- if (regs->pcs_base[phy] == SJA1105_RSV_ADDR)
- return -ENODEV;
- addr = (mmd << 16) | (reg & GENMASK(15, 0));
- bank = addr >> 8;
- offset = addr & GENMASK(7, 0);
- /* This addressing scheme reserves register 0xff for the bank address
- * register, so that can never be addressed.
- */
- if (offset == 0xff)
- return -ENODEV;
- tmp = bank;
- sja1105_packing(packed_buf, &tmp, 31, 0, size, PACK);
- rc = sja1105_xfer_buf(priv, SPI_WRITE,
- regs->pcs_base[phy] + SJA1110_PCS_BANK_REG,
- packed_buf, size);
- if (rc < 0)
- return rc;
- rc = sja1105_xfer_buf(priv, SPI_READ, regs->pcs_base[phy] + offset,
- packed_buf, size);
- if (rc < 0)
- return rc;
- sja1105_packing(packed_buf, &tmp, 31, 0, size, UNPACK);
- return tmp & 0xffff;
- }
- static int sja1110_pcs_mdio_write(struct mii_dev *bus, int phy, int mmd,
- int reg, u16 val)
- {
- struct sja1105_private *priv = bus->priv;
- const struct sja1105_regs *regs = priv->info->regs;
- u8 packed_buf[SJA1105_SIZE_MDIO_CMD] = {0};
- const int size = SJA1105_SIZE_MDIO_CMD;
- int offset, bank;
- u64 addr, tmp;
- int rc;
- if (mmd == MDIO_DEVAD_NONE)
- return -ENODEV;
- if (regs->pcs_base[phy] == SJA1105_RSV_ADDR)
- return -ENODEV;
- addr = (mmd << 16) | (reg & GENMASK(15, 0));
- bank = addr >> 8;
- offset = addr & GENMASK(7, 0);
- /* This addressing scheme reserves register 0xff for the bank address
- * register, so that can never be addressed.
- */
- if (offset == 0xff)
- return -ENODEV;
- tmp = bank;
- sja1105_packing(packed_buf, &tmp, 31, 0, size, PACK);
- rc = sja1105_xfer_buf(priv, SPI_WRITE,
- regs->pcs_base[phy] + SJA1110_PCS_BANK_REG,
- packed_buf, size);
- if (rc < 0)
- return rc;
- tmp = val;
- sja1105_packing(packed_buf, &tmp, 31, 0, size, PACK);
- return sja1105_xfer_buf(priv, SPI_WRITE, regs->pcs_base[phy] + offset,
- packed_buf, size);
- }
- static int sja1105_mdiobus_register(struct sja1105_private *priv)
- {
- struct udevice *dev = priv->dev;
- struct mii_dev *bus;
- int rc;
- if (!priv->info->pcs_mdio_read || !priv->info->pcs_mdio_write)
- return 0;
- bus = mdio_alloc();
- if (!bus)
- return -ENOMEM;
- snprintf(bus->name, MDIO_NAME_LEN, "%s-pcs", dev->name);
- bus->read = priv->info->pcs_mdio_read;
- bus->write = priv->info->pcs_mdio_write;
- bus->priv = priv;
- rc = mdio_register(bus);
- if (rc) {
- mdio_free(bus);
- return rc;
- }
- priv->mdio_pcs = bus;
- return 0;
- }
- static void sja1105_mdiobus_unregister(struct sja1105_private *priv)
- {
- if (!priv->mdio_pcs)
- return;
- mdio_unregister(priv->mdio_pcs);
- mdio_free(priv->mdio_pcs);
- }
- static const struct sja1105_regs sja1105et_regs = {
- .device_id = 0x0,
- .prod_id = 0x100BC3,
- .status = 0x1,
- .port_control = 0x11,
- .config = 0x020000,
- .rgu = 0x100440,
- /* UM10944.pdf, Table 86, ACU Register overview */
- .pad_mii_tx = {0x100800, 0x100802, 0x100804, 0x100806, 0x100808},
- .pad_mii_rx = {0x100801, 0x100803, 0x100805, 0x100807, 0x100809},
- .rmii_pll1 = 0x10000A,
- .cgu_idiv = {0x10000B, 0x10000C, 0x10000D, 0x10000E, 0x10000F},
- /* UM10944.pdf, Table 78, CGU Register overview */
- .mii_tx_clk = {0x100013, 0x10001A, 0x100021, 0x100028, 0x10002F},
- .mii_rx_clk = {0x100014, 0x10001B, 0x100022, 0x100029, 0x100030},
- .mii_ext_tx_clk = {0x100018, 0x10001F, 0x100026, 0x10002D, 0x100034},
- .mii_ext_rx_clk = {0x100019, 0x100020, 0x100027, 0x10002E, 0x100035},
- .rgmii_tx_clk = {0x100016, 0x10001D, 0x100024, 0x10002B, 0x100032},
- .rmii_ref_clk = {0x100015, 0x10001C, 0x100023, 0x10002A, 0x100031},
- .rmii_ext_tx_clk = {0x100018, 0x10001F, 0x100026, 0x10002D, 0x100034},
- };
- static const struct sja1105_regs sja1105pqrs_regs = {
- .device_id = 0x0,
- .prod_id = 0x100BC3,
- .status = 0x1,
- .port_control = 0x12,
- .config = 0x020000,
- .rgu = 0x100440,
- /* UM10944.pdf, Table 86, ACU Register overview */
- .pad_mii_tx = {0x100800, 0x100802, 0x100804, 0x100806, 0x100808},
- .pad_mii_rx = {0x100801, 0x100803, 0x100805, 0x100807, 0x100809},
- .pad_mii_id = {0x100810, 0x100811, 0x100812, 0x100813, 0x100814},
- .rmii_pll1 = 0x10000A,
- .cgu_idiv = {0x10000B, 0x10000C, 0x10000D, 0x10000E, 0x10000F},
- /* UM11040.pdf, Table 114 */
- .mii_tx_clk = {0x100013, 0x100019, 0x10001F, 0x100025, 0x10002B},
- .mii_rx_clk = {0x100014, 0x10001A, 0x100020, 0x100026, 0x10002C},
- .mii_ext_tx_clk = {0x100017, 0x10001D, 0x100023, 0x100029, 0x10002F},
- .mii_ext_rx_clk = {0x100018, 0x10001E, 0x100024, 0x10002A, 0x100030},
- .rgmii_tx_clk = {0x100016, 0x10001C, 0x100022, 0x100028, 0x10002E},
- .rmii_ref_clk = {0x100015, 0x10001B, 0x100021, 0x100027, 0x10002D},
- .rmii_ext_tx_clk = {0x100017, 0x10001D, 0x100023, 0x100029, 0x10002F},
- };
- static const struct sja1105_regs sja1110_regs = {
- .device_id = SJA1110_SPI_ADDR(0x0),
- .prod_id = SJA1110_ACU_ADDR(0xf00),
- .status = SJA1110_SPI_ADDR(0x4),
- .port_control = SJA1110_SPI_ADDR(0x50), /* actually INHIB_TX */
- .config = 0x020000,
- .rgu = SJA1110_RGU_ADDR(0x100), /* Reset Control Register 0 */
- /* Ports 2 and 3 are capable of xMII, but there isn't anything to
- * configure in the CGU/ACU for them.
- */
- .pad_mii_tx = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR},
- .pad_mii_rx = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR},
- .pad_mii_id = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1110_ACU_ADDR(0x18), SJA1110_ACU_ADDR(0x28),
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR},
- .rmii_pll1 = SJA1105_RSV_ADDR,
- .cgu_idiv = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR},
- .mii_tx_clk = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR},
- .mii_rx_clk = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR},
- .mii_ext_tx_clk = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR},
- .mii_ext_rx_clk = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR},
- .rgmii_tx_clk = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR},
- .rmii_ref_clk = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR},
- .rmii_ext_tx_clk = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR},
- .pcs_base = {SJA1105_RSV_ADDR, 0x1c1400, 0x1c1800, 0x1c1c00, 0x1c2000,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
- SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR},
- };
- enum sja1105_switch_id {
- SJA1105E = 0,
- SJA1105T,
- SJA1105P,
- SJA1105Q,
- SJA1105R,
- SJA1105S,
- SJA1110A,
- SJA1110B,
- SJA1110C,
- SJA1110D,
- SJA1105_MAX_SWITCH_ID,
- };
- static const struct sja1105_info sja1105_info[] = {
- [SJA1105E] = {
- .device_id = SJA1105E_DEVICE_ID,
- .part_no = SJA1105ET_PART_NO,
- .static_ops = sja1105et_table_ops,
- .reset_cmd = sja1105et_reset_cmd,
- .regs = &sja1105et_regs,
- .port_speed = {
- [SJA1105_SPEED_AUTO] = 0,
- [SJA1105_SPEED_10MBPS] = 3,
- [SJA1105_SPEED_100MBPS] = 2,
- [SJA1105_SPEED_1000MBPS] = 1,
- },
- .supports_mii = {true, true, true, true, true},
- .supports_rmii = {true, true, true, true, true},
- .supports_rgmii = {true, true, true, true, true},
- .name = "SJA1105E",
- },
- [SJA1105T] = {
- .device_id = SJA1105T_DEVICE_ID,
- .part_no = SJA1105ET_PART_NO,
- .static_ops = sja1105et_table_ops,
- .reset_cmd = sja1105et_reset_cmd,
- .regs = &sja1105et_regs,
- .port_speed = {
- [SJA1105_SPEED_AUTO] = 0,
- [SJA1105_SPEED_10MBPS] = 3,
- [SJA1105_SPEED_100MBPS] = 2,
- [SJA1105_SPEED_1000MBPS] = 1,
- },
- .supports_mii = {true, true, true, true, true},
- .supports_rmii = {true, true, true, true, true},
- .supports_rgmii = {true, true, true, true, true},
- .name = "SJA1105T",
- },
- [SJA1105P] = {
- .device_id = SJA1105PR_DEVICE_ID,
- .part_no = SJA1105P_PART_NO,
- .static_ops = sja1105pqrs_table_ops,
- .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay,
- .reset_cmd = sja1105pqrs_reset_cmd,
- .regs = &sja1105pqrs_regs,
- .port_speed = {
- [SJA1105_SPEED_AUTO] = 0,
- [SJA1105_SPEED_10MBPS] = 3,
- [SJA1105_SPEED_100MBPS] = 2,
- [SJA1105_SPEED_1000MBPS] = 1,
- },
- .supports_mii = {true, true, true, true, true},
- .supports_rmii = {true, true, true, true, true},
- .supports_rgmii = {true, true, true, true, true},
- .name = "SJA1105P",
- },
- [SJA1105Q] = {
- .device_id = SJA1105QS_DEVICE_ID,
- .part_no = SJA1105Q_PART_NO,
- .static_ops = sja1105pqrs_table_ops,
- .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay,
- .reset_cmd = sja1105pqrs_reset_cmd,
- .regs = &sja1105pqrs_regs,
- .port_speed = {
- [SJA1105_SPEED_AUTO] = 0,
- [SJA1105_SPEED_10MBPS] = 3,
- [SJA1105_SPEED_100MBPS] = 2,
- [SJA1105_SPEED_1000MBPS] = 1,
- },
- .supports_mii = {true, true, true, true, true},
- .supports_rmii = {true, true, true, true, true},
- .supports_rgmii = {true, true, true, true, true},
- .name = "SJA1105Q",
- },
- [SJA1105R] = {
- .device_id = SJA1105PR_DEVICE_ID,
- .part_no = SJA1105R_PART_NO,
- .static_ops = sja1105pqrs_table_ops,
- .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay,
- .reset_cmd = sja1105pqrs_reset_cmd,
- .regs = &sja1105pqrs_regs,
- .pcs_mdio_read = sja1105_pcs_mdio_read,
- .pcs_mdio_write = sja1105_pcs_mdio_write,
- .pma_config = sja1105_pma_config,
- .port_speed = {
- [SJA1105_SPEED_AUTO] = 0,
- [SJA1105_SPEED_10MBPS] = 3,
- [SJA1105_SPEED_100MBPS] = 2,
- [SJA1105_SPEED_1000MBPS] = 1,
- },
- .supports_mii = {true, true, true, true, true},
- .supports_rmii = {true, true, true, true, true},
- .supports_rgmii = {true, true, true, true, true},
- .supports_sgmii = {false, false, false, false, true},
- .name = "SJA1105R",
- },
- [SJA1105S] = {
- .device_id = SJA1105QS_DEVICE_ID,
- .part_no = SJA1105S_PART_NO,
- .static_ops = sja1105pqrs_table_ops,
- .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay,
- .reset_cmd = sja1105pqrs_reset_cmd,
- .regs = &sja1105pqrs_regs,
- .pcs_mdio_read = sja1105_pcs_mdio_read,
- .pcs_mdio_write = sja1105_pcs_mdio_write,
- .pma_config = sja1105_pma_config,
- .port_speed = {
- [SJA1105_SPEED_AUTO] = 0,
- [SJA1105_SPEED_10MBPS] = 3,
- [SJA1105_SPEED_100MBPS] = 2,
- [SJA1105_SPEED_1000MBPS] = 1,
- },
- .supports_mii = {true, true, true, true, true},
- .supports_rmii = {true, true, true, true, true},
- .supports_rgmii = {true, true, true, true, true},
- .supports_sgmii = {false, false, false, false, true},
- .name = "SJA1105S",
- },
- [SJA1110A] = {
- .device_id = SJA1110_DEVICE_ID,
- .part_no = SJA1110A_PART_NO,
- .static_ops = sja1110_table_ops,
- .setup_rgmii_delay = sja1110_setup_rgmii_delay,
- .reset_cmd = sja1110_reset_cmd,
- .regs = &sja1110_regs,
- .pcs_mdio_read = sja1110_pcs_mdio_read,
- .pcs_mdio_write = sja1110_pcs_mdio_write,
- .pma_config = sja1110_pma_config,
- .port_speed = {
- [SJA1105_SPEED_AUTO] = 0,
- [SJA1105_SPEED_10MBPS] = 4,
- [SJA1105_SPEED_100MBPS] = 3,
- [SJA1105_SPEED_1000MBPS] = 2,
- },
- .supports_mii = {true, true, true, true, false,
- true, true, true, true, true, true},
- .supports_rmii = {false, false, true, true, false,
- false, false, false, false, false, false},
- .supports_rgmii = {false, false, true, true, false,
- false, false, false, false, false, false},
- .supports_sgmii = {false, true, true, true, true,
- false, false, false, false, false, false},
- .name = "SJA1110A",
- },
- [SJA1110B] = {
- .device_id = SJA1110_DEVICE_ID,
- .part_no = SJA1110B_PART_NO,
- .static_ops = sja1110_table_ops,
- .setup_rgmii_delay = sja1110_setup_rgmii_delay,
- .reset_cmd = sja1110_reset_cmd,
- .regs = &sja1110_regs,
- .pcs_mdio_read = sja1110_pcs_mdio_read,
- .pcs_mdio_write = sja1110_pcs_mdio_write,
- .pma_config = sja1110_pma_config,
- .port_speed = {
- [SJA1105_SPEED_AUTO] = 0,
- [SJA1105_SPEED_10MBPS] = 4,
- [SJA1105_SPEED_100MBPS] = 3,
- [SJA1105_SPEED_1000MBPS] = 2,
- },
- .supports_mii = {true, true, true, true, false,
- true, true, true, true, true, false},
- .supports_rmii = {false, false, true, true, false,
- false, false, false, false, false, false},
- .supports_rgmii = {false, false, true, true, false,
- false, false, false, false, false, false},
- .supports_sgmii = {false, false, false, true, true,
- false, false, false, false, false, false},
- .name = "SJA1110B",
- },
- [SJA1110C] = {
- .device_id = SJA1110_DEVICE_ID,
- .part_no = SJA1110C_PART_NO,
- .static_ops = sja1110_table_ops,
- .setup_rgmii_delay = sja1110_setup_rgmii_delay,
- .reset_cmd = sja1110_reset_cmd,
- .regs = &sja1110_regs,
- .pcs_mdio_read = sja1110_pcs_mdio_read,
- .pcs_mdio_write = sja1110_pcs_mdio_write,
- .pma_config = sja1110_pma_config,
- .port_speed = {
- [SJA1105_SPEED_AUTO] = 0,
- [SJA1105_SPEED_10MBPS] = 4,
- [SJA1105_SPEED_100MBPS] = 3,
- [SJA1105_SPEED_1000MBPS] = 2,
- },
- .supports_mii = {true, true, true, true, false,
- true, true, true, false, false, false},
- .supports_rmii = {false, false, true, true, false,
- false, false, false, false, false, false},
- .supports_rgmii = {false, false, true, true, false,
- false, false, false, false, false, false},
- .supports_sgmii = {false, false, false, false, true,
- false, false, false, false, false, false},
- .name = "SJA1110C",
- },
- [SJA1110D] = {
- .device_id = SJA1110_DEVICE_ID,
- .part_no = SJA1110D_PART_NO,
- .static_ops = sja1110_table_ops,
- .setup_rgmii_delay = sja1110_setup_rgmii_delay,
- .reset_cmd = sja1110_reset_cmd,
- .regs = &sja1110_regs,
- .pcs_mdio_read = sja1110_pcs_mdio_read,
- .pcs_mdio_write = sja1110_pcs_mdio_write,
- .pma_config = sja1110_pma_config,
- .port_speed = {
- [SJA1105_SPEED_AUTO] = 0,
- [SJA1105_SPEED_10MBPS] = 4,
- [SJA1105_SPEED_100MBPS] = 3,
- [SJA1105_SPEED_1000MBPS] = 2,
- },
- .supports_mii = {true, false, true, false, false,
- true, true, true, false, false, false},
- .supports_rmii = {false, false, true, false, false,
- false, false, false, false, false, false},
- .supports_rgmii = {false, false, true, false, false,
- false, false, false, false, false, false},
- .supports_sgmii = {false, true, true, true, true,
- false, false, false, false, false, false},
- .name = "SJA1110D",
- },
- };
- struct sja1105_status {
- u64 configs;
- u64 crcchkl;
- u64 ids;
- u64 crcchkg;
- };
- static void sja1105_status_unpack(void *buf, struct sja1105_status *status)
- {
- sja1105_packing(buf, &status->configs, 31, 31, 4, UNPACK);
- sja1105_packing(buf, &status->crcchkl, 30, 30, 4, UNPACK);
- sja1105_packing(buf, &status->ids, 29, 29, 4, UNPACK);
- sja1105_packing(buf, &status->crcchkg, 28, 28, 4, UNPACK);
- }
- static int sja1105_status_get(struct sja1105_private *priv,
- struct sja1105_status *status)
- {
- const struct sja1105_regs *regs = priv->info->regs;
- u8 packed_buf[4];
- int rc;
- rc = sja1105_xfer_buf(priv, SPI_READ, regs->status, packed_buf, 4);
- if (rc < 0)
- return rc;
- sja1105_status_unpack(packed_buf, status);
- return 0;
- }
- /* Not const because unpacking priv->static_config into buffers and preparing
- * for upload requires the recalculation of table CRCs and updating the
- * structures with these.
- */
- static int
- static_config_buf_prepare_for_upload(struct sja1105_private *priv,
- void *config_buf, int buf_len)
- {
- struct sja1105_static_config *config = &priv->static_config;
- struct sja1105_table_header final_header;
- char *final_header_ptr;
- int crc_len;
- /* Write Device ID and config tables to config_buf */
- sja1105_static_config_pack(config_buf, config);
- /* Recalculate CRC of the last header (right now 0xDEADBEEF).
- * Don't include the CRC field itself.
- */
- crc_len = buf_len - 4;
- /* Read the whole table header */
- final_header_ptr = config_buf + buf_len - SJA1105_SIZE_TABLE_HEADER;
- sja1105_table_header_packing(final_header_ptr, &final_header, UNPACK);
- /* Modify */
- final_header.crc = sja1105_crc32(config_buf, crc_len);
- /* Rewrite */
- sja1105_table_header_packing(final_header_ptr, &final_header, PACK);
- return 0;
- }
- static int sja1105_static_config_upload(struct sja1105_private *priv)
- {
- struct sja1105_static_config *config = &priv->static_config;
- const struct sja1105_regs *regs = priv->info->regs;
- struct sja1105_status status;
- u8 *config_buf;
- int buf_len;
- int rc;
- buf_len = sja1105_static_config_get_length(config);
- config_buf = calloc(buf_len, sizeof(char));
- if (!config_buf)
- return -ENOMEM;
- rc = static_config_buf_prepare_for_upload(priv, config_buf, buf_len);
- if (rc < 0) {
- printf("Invalid config, cannot upload\n");
- rc = -EINVAL;
- goto out;
- }
- /* Put the SJA1105 in programming mode */
- rc = priv->info->reset_cmd(priv);
- if (rc < 0) {
- printf("Failed to reset switch\n");
- goto out;
- }
- /* Wait for the switch to come out of reset */
- udelay(1000);
- /* Upload the static config to the device */
- rc = sja1105_xfer_buf(priv, SPI_WRITE, regs->config,
- config_buf, buf_len);
- if (rc < 0) {
- printf("Failed to upload config\n");
- goto out;
- }
- /* Check that SJA1105 responded well to the config upload */
- rc = sja1105_status_get(priv, &status);
- if (rc < 0)
- goto out;
- if (status.ids == 1) {
- printf("Mismatch between hardware and static config device id. "
- "Wrote 0x%llx, wants 0x%llx\n",
- config->device_id, priv->info->device_id);
- rc = -EIO;
- goto out;
- }
- if (status.crcchkl == 1 || status.crcchkg == 1) {
- printf("Switch reported invalid CRC on static config\n");
- rc = -EIO;
- goto out;
- }
- if (status.configs == 0) {
- printf("Switch reported that config is invalid\n");
- rc = -EIO;
- goto out;
- }
- out:
- free(config_buf);
- return rc;
- }
- static int sja1105_static_config_reload(struct sja1105_private *priv)
- {
- int rc;
- rc = sja1105_static_config_upload(priv);
- if (rc < 0) {
- printf("Failed to load static config: %d\n", rc);
- return rc;
- }
- /* Configure the CGU (PHY link modes and speeds) */
- rc = sja1105_clocking_setup(priv);
- if (rc < 0) {
- printf("Failed to configure MII clocking: %d\n", rc);
- return rc;
- }
- return 0;
- }
- static int sja1105_port_probe(struct udevice *dev, int port,
- struct phy_device *phy)
- {
- struct sja1105_private *priv = dev_get_priv(dev);
- ofnode node = dsa_port_get_ofnode(dev, port);
- phy_interface_t phy_mode = phy->interface;
- priv->xpcs_cfg[port].inband_an = ofnode_eth_uses_inband_aneg(node);
- if (phy_mode == PHY_INTERFACE_MODE_MII ||
- phy_mode == PHY_INTERFACE_MODE_RMII) {
- phy->supported &= PHY_BASIC_FEATURES;
- phy->advertising &= PHY_BASIC_FEATURES;
- } else {
- phy->supported &= PHY_GBIT_FEATURES;
- phy->advertising &= PHY_GBIT_FEATURES;
- }
- return phy_config(phy);
- }
- static int sja1105_port_enable(struct udevice *dev, int port,
- struct phy_device *phy)
- {
- struct sja1105_private *priv = dev_get_priv(dev);
- phy_interface_t phy_mode = phy->interface;
- struct sja1105_xmii_params_entry *mii;
- struct sja1105_mac_config_entry *mac;
- int rc;
- rc = phy_startup(phy);
- if (rc)
- return rc;
- mii = priv->static_config.tables[BLK_IDX_XMII_PARAMS].entries;
- mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries;
- switch (phy_mode) {
- case PHY_INTERFACE_MODE_MII:
- if (!priv->info->supports_mii[port])
- goto unsupported;
- mii->xmii_mode[port] = XMII_MODE_MII;
- break;
- case PHY_INTERFACE_MODE_RMII:
- if (!priv->info->supports_rmii[port])
- goto unsupported;
- mii->xmii_mode[port] = XMII_MODE_RMII;
- break;
- case PHY_INTERFACE_MODE_RGMII:
- case PHY_INTERFACE_MODE_RGMII_ID:
- case PHY_INTERFACE_MODE_RGMII_RXID:
- case PHY_INTERFACE_MODE_RGMII_TXID:
- if (!priv->info->supports_rgmii[port])
- goto unsupported;
- mii->xmii_mode[port] = XMII_MODE_RGMII;
- break;
- case PHY_INTERFACE_MODE_SGMII:
- if (!priv->info->supports_sgmii[port])
- goto unsupported;
- mii->xmii_mode[port] = XMII_MODE_SGMII;
- mii->special[port] = true;
- break;
- unsupported:
- default:
- dev_err(dev, "Unsupported PHY mode %d on port %d!\n",
- phy_mode, port);
- return -EINVAL;
- }
- /* RevMII, RevRMII not supported */
- mii->phy_mac[port] = XMII_MAC;
- /* Let the PHY handle the RGMII delays, if present. */
- if (phy->phy_id == PHY_FIXED_ID) {
- if (phy_mode == PHY_INTERFACE_MODE_RGMII_RXID ||
- phy_mode == PHY_INTERFACE_MODE_RGMII_ID)
- priv->rgmii_rx_delay[port] = true;
- if (phy_mode == PHY_INTERFACE_MODE_RGMII_TXID ||
- phy_mode == PHY_INTERFACE_MODE_RGMII_ID)
- priv->rgmii_tx_delay[port] = true;
- if ((priv->rgmii_rx_delay[port] ||
- priv->rgmii_tx_delay[port]) &&
- !priv->info->setup_rgmii_delay) {
- printf("Chip does not support internal RGMII delays\n");
- return -EINVAL;
- }
- }
- if (mii->xmii_mode[port] == XMII_MODE_SGMII) {
- mac[port].speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS];
- priv->xpcs_cfg[port].speed = phy->speed;
- } else if (phy->speed == SPEED_1000) {
- mac[port].speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS];
- } else if (phy->speed == SPEED_100) {
- mac[port].speed = priv->info->port_speed[SJA1105_SPEED_100MBPS];
- } else if (phy->speed == SPEED_10) {
- mac[port].speed = priv->info->port_speed[SJA1105_SPEED_10MBPS];
- } else {
- printf("Invalid PHY speed %d on port %d\n", phy->speed, port);
- return -EINVAL;
- }
- return sja1105_static_config_reload(priv);
- }
- static void sja1105_port_disable(struct udevice *dev, int port,
- struct phy_device *phy)
- {
- phy_shutdown(phy);
- }
- static int sja1105_xmit(struct udevice *dev, int port, void *packet, int length)
- {
- struct sja1105_private *priv = dev_get_priv(dev);
- u8 *from = (u8 *)packet + VLAN_HLEN;
- struct vlan_ethhdr *hdr = packet;
- u8 *dest = (u8 *)packet;
- memmove(dest, from, 2 * ETH_ALEN);
- hdr->h_vlan_proto = htons(ETH_P_SJA1105);
- hdr->h_vlan_TCI = htons(priv->pvid[port]);
- return 0;
- }
- static int sja1105_rcv(struct udevice *dev, int *port, void *packet, int length)
- {
- struct vlan_ethhdr *hdr = packet;
- u8 *dest = packet + VLAN_HLEN;
- u8 *from = packet;
- if (ntohs(hdr->h_vlan_proto) != ETH_P_SJA1105)
- return -EINVAL;
- *port = ntohs(hdr->h_vlan_TCI) & DSA_8021Q_PORT_MASK;
- memmove(dest, from, 2 * ETH_ALEN);
- return 0;
- }
- static const struct dsa_ops sja1105_dsa_ops = {
- .port_probe = sja1105_port_probe,
- .port_enable = sja1105_port_enable,
- .port_disable = sja1105_port_disable,
- .xmit = sja1105_xmit,
- .rcv = sja1105_rcv,
- };
- static int sja1105_init(struct sja1105_private *priv)
- {
- int rc;
- rc = sja1105_static_config_init(priv);
- if (rc) {
- printf("Failed to initialize static config: %d\n", rc);
- return rc;
- }
- rc = sja1105_mdiobus_register(priv);
- if (rc) {
- printf("Failed to register MDIO bus: %d\n", rc);
- goto err_mdiobus_register;
- }
- return 0;
- err_mdiobus_register:
- sja1105_static_config_free(&priv->static_config);
- return rc;
- }
- static int sja1105_check_device_id(struct sja1105_private *priv)
- {
- const struct sja1105_regs *regs = priv->info->regs;
- u8 packed_buf[SJA1105_SIZE_DEVICE_ID] = {0};
- enum sja1105_switch_id id;
- u64 device_id;
- u64 part_no;
- int rc;
- rc = sja1105_xfer_buf(priv, SPI_READ, regs->device_id, packed_buf,
- SJA1105_SIZE_DEVICE_ID);
- if (rc < 0)
- return rc;
- sja1105_packing(packed_buf, &device_id, 31, 0, SJA1105_SIZE_DEVICE_ID,
- UNPACK);
- rc = sja1105_xfer_buf(priv, SPI_READ, regs->prod_id, packed_buf,
- SJA1105_SIZE_DEVICE_ID);
- if (rc < 0)
- return rc;
- sja1105_packing(packed_buf, &part_no, 19, 4, SJA1105_SIZE_DEVICE_ID,
- UNPACK);
- for (id = 0; id < SJA1105_MAX_SWITCH_ID; id++) {
- const struct sja1105_info *info = &sja1105_info[id];
- /* Is what's been probed in our match table at all? */
- if (info->device_id != device_id || info->part_no != part_no)
- continue;
- /* But is it what's in the device tree? */
- if (priv->info->device_id != device_id ||
- priv->info->part_no != part_no) {
- printf("Device tree specifies chip %s but found %s, please fix it!\n",
- priv->info->name, info->name);
- /* It isn't. No problem, pick that up. */
- priv->info = info;
- }
- return 0;
- }
- printf("Unexpected {device ID, part number}: 0x%llx 0x%llx\n",
- device_id, part_no);
- return -ENODEV;
- }
- static int sja1105_probe(struct udevice *dev)
- {
- enum sja1105_switch_id id = dev_get_driver_data(dev);
- struct sja1105_private *priv = dev_get_priv(dev);
- int rc;
- if (ofnode_valid(dev_ofnode(dev)) &&
- !ofnode_is_enabled(dev_ofnode(dev))) {
- dev_dbg(dev, "switch disabled\n");
- return -ENODEV;
- }
- priv->info = &sja1105_info[id];
- priv->dev = dev;
- rc = sja1105_check_device_id(priv);
- if (rc < 0) {
- dev_err(dev, "Device ID check failed: %d\n", rc);
- return rc;
- }
- dsa_set_tagging(dev, VLAN_HLEN, 0);
- return sja1105_init(priv);
- }
- static int sja1105_remove(struct udevice *dev)
- {
- struct sja1105_private *priv = dev_get_priv(dev);
- sja1105_mdiobus_unregister(priv);
- sja1105_static_config_free(&priv->static_config);
- return 0;
- }
- static const struct udevice_id sja1105_ids[] = {
- { .compatible = "nxp,sja1105e", .data = SJA1105E },
- { .compatible = "nxp,sja1105t", .data = SJA1105T },
- { .compatible = "nxp,sja1105p", .data = SJA1105P },
- { .compatible = "nxp,sja1105q", .data = SJA1105Q },
- { .compatible = "nxp,sja1105r", .data = SJA1105R },
- { .compatible = "nxp,sja1105s", .data = SJA1105S },
- { .compatible = "nxp,sja1110a", .data = SJA1110A },
- { .compatible = "nxp,sja1110b", .data = SJA1110B },
- { .compatible = "nxp,sja1110c", .data = SJA1110C },
- { .compatible = "nxp,sja1110d", .data = SJA1110D },
- { }
- };
- U_BOOT_DRIVER(sja1105) = {
- .name = "sja1105",
- .id = UCLASS_DSA,
- .of_match = sja1105_ids,
- .probe = sja1105_probe,
- .remove = sja1105_remove,
- .ops = &sja1105_dsa_ops,
- .priv_auto = sizeof(struct sja1105_private),
- };
|