12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * Microchip switch driver main logic
- *
- * Copyright (C) 2017-2019 Microchip Technology Inc.
- */
- #include <linux/delay.h>
- #include <linux/export.h>
- #include <linux/gpio/consumer.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/platform_data/microchip-ksz.h>
- #include <linux/phy.h>
- #include <linux/etherdevice.h>
- #include <linux/if_bridge.h>
- #include <linux/irq.h>
- #include <linux/irqdomain.h>
- #include <linux/of_mdio.h>
- #include <linux/of_device.h>
- #include <linux/of_net.h>
- #include <linux/micrel_phy.h>
- #include <net/dsa.h>
- #include <net/switchdev.h>
- #include "ksz_common.h"
- #include "ksz8.h"
- #include "ksz9477.h"
- #include "lan937x.h"
- #define MIB_COUNTER_NUM 0x20
- struct ksz_stats_raw {
- u64 rx_hi;
- u64 rx_undersize;
- u64 rx_fragments;
- u64 rx_oversize;
- u64 rx_jabbers;
- u64 rx_symbol_err;
- u64 rx_crc_err;
- u64 rx_align_err;
- u64 rx_mac_ctrl;
- u64 rx_pause;
- u64 rx_bcast;
- u64 rx_mcast;
- u64 rx_ucast;
- u64 rx_64_or_less;
- u64 rx_65_127;
- u64 rx_128_255;
- u64 rx_256_511;
- u64 rx_512_1023;
- u64 rx_1024_1522;
- u64 rx_1523_2000;
- u64 rx_2001;
- u64 tx_hi;
- u64 tx_late_col;
- u64 tx_pause;
- u64 tx_bcast;
- u64 tx_mcast;
- u64 tx_ucast;
- u64 tx_deferred;
- u64 tx_total_col;
- u64 tx_exc_col;
- u64 tx_single_col;
- u64 tx_mult_col;
- u64 rx_total;
- u64 tx_total;
- u64 rx_discards;
- u64 tx_discards;
- };
- static const struct ksz_mib_names ksz88xx_mib_names[] = {
- { 0x00, "rx" },
- { 0x01, "rx_hi" },
- { 0x02, "rx_undersize" },
- { 0x03, "rx_fragments" },
- { 0x04, "rx_oversize" },
- { 0x05, "rx_jabbers" },
- { 0x06, "rx_symbol_err" },
- { 0x07, "rx_crc_err" },
- { 0x08, "rx_align_err" },
- { 0x09, "rx_mac_ctrl" },
- { 0x0a, "rx_pause" },
- { 0x0b, "rx_bcast" },
- { 0x0c, "rx_mcast" },
- { 0x0d, "rx_ucast" },
- { 0x0e, "rx_64_or_less" },
- { 0x0f, "rx_65_127" },
- { 0x10, "rx_128_255" },
- { 0x11, "rx_256_511" },
- { 0x12, "rx_512_1023" },
- { 0x13, "rx_1024_1522" },
- { 0x14, "tx" },
- { 0x15, "tx_hi" },
- { 0x16, "tx_late_col" },
- { 0x17, "tx_pause" },
- { 0x18, "tx_bcast" },
- { 0x19, "tx_mcast" },
- { 0x1a, "tx_ucast" },
- { 0x1b, "tx_deferred" },
- { 0x1c, "tx_total_col" },
- { 0x1d, "tx_exc_col" },
- { 0x1e, "tx_single_col" },
- { 0x1f, "tx_mult_col" },
- { 0x100, "rx_discards" },
- { 0x101, "tx_discards" },
- };
- static const struct ksz_mib_names ksz9477_mib_names[] = {
- { 0x00, "rx_hi" },
- { 0x01, "rx_undersize" },
- { 0x02, "rx_fragments" },
- { 0x03, "rx_oversize" },
- { 0x04, "rx_jabbers" },
- { 0x05, "rx_symbol_err" },
- { 0x06, "rx_crc_err" },
- { 0x07, "rx_align_err" },
- { 0x08, "rx_mac_ctrl" },
- { 0x09, "rx_pause" },
- { 0x0A, "rx_bcast" },
- { 0x0B, "rx_mcast" },
- { 0x0C, "rx_ucast" },
- { 0x0D, "rx_64_or_less" },
- { 0x0E, "rx_65_127" },
- { 0x0F, "rx_128_255" },
- { 0x10, "rx_256_511" },
- { 0x11, "rx_512_1023" },
- { 0x12, "rx_1024_1522" },
- { 0x13, "rx_1523_2000" },
- { 0x14, "rx_2001" },
- { 0x15, "tx_hi" },
- { 0x16, "tx_late_col" },
- { 0x17, "tx_pause" },
- { 0x18, "tx_bcast" },
- { 0x19, "tx_mcast" },
- { 0x1A, "tx_ucast" },
- { 0x1B, "tx_deferred" },
- { 0x1C, "tx_total_col" },
- { 0x1D, "tx_exc_col" },
- { 0x1E, "tx_single_col" },
- { 0x1F, "tx_mult_col" },
- { 0x80, "rx_total" },
- { 0x81, "tx_total" },
- { 0x82, "rx_discards" },
- { 0x83, "tx_discards" },
- };
- static const struct ksz_dev_ops ksz8_dev_ops = {
- .setup = ksz8_setup,
- .get_port_addr = ksz8_get_port_addr,
- .cfg_port_member = ksz8_cfg_port_member,
- .flush_dyn_mac_table = ksz8_flush_dyn_mac_table,
- .port_setup = ksz8_port_setup,
- .r_phy = ksz8_r_phy,
- .w_phy = ksz8_w_phy,
- .r_mib_cnt = ksz8_r_mib_cnt,
- .r_mib_pkt = ksz8_r_mib_pkt,
- .freeze_mib = ksz8_freeze_mib,
- .port_init_cnt = ksz8_port_init_cnt,
- .fdb_dump = ksz8_fdb_dump,
- .mdb_add = ksz8_mdb_add,
- .mdb_del = ksz8_mdb_del,
- .vlan_filtering = ksz8_port_vlan_filtering,
- .vlan_add = ksz8_port_vlan_add,
- .vlan_del = ksz8_port_vlan_del,
- .mirror_add = ksz8_port_mirror_add,
- .mirror_del = ksz8_port_mirror_del,
- .get_caps = ksz8_get_caps,
- .config_cpu_port = ksz8_config_cpu_port,
- .enable_stp_addr = ksz8_enable_stp_addr,
- .reset = ksz8_reset_switch,
- .init = ksz8_switch_init,
- .exit = ksz8_switch_exit,
- };
- static void ksz9477_phylink_mac_link_up(struct ksz_device *dev, int port,
- unsigned int mode,
- phy_interface_t interface,
- struct phy_device *phydev, int speed,
- int duplex, bool tx_pause,
- bool rx_pause);
- static const struct ksz_dev_ops ksz9477_dev_ops = {
- .setup = ksz9477_setup,
- .get_port_addr = ksz9477_get_port_addr,
- .cfg_port_member = ksz9477_cfg_port_member,
- .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
- .port_setup = ksz9477_port_setup,
- .set_ageing_time = ksz9477_set_ageing_time,
- .r_phy = ksz9477_r_phy,
- .w_phy = ksz9477_w_phy,
- .r_mib_cnt = ksz9477_r_mib_cnt,
- .r_mib_pkt = ksz9477_r_mib_pkt,
- .r_mib_stat64 = ksz_r_mib_stats64,
- .freeze_mib = ksz9477_freeze_mib,
- .port_init_cnt = ksz9477_port_init_cnt,
- .vlan_filtering = ksz9477_port_vlan_filtering,
- .vlan_add = ksz9477_port_vlan_add,
- .vlan_del = ksz9477_port_vlan_del,
- .mirror_add = ksz9477_port_mirror_add,
- .mirror_del = ksz9477_port_mirror_del,
- .get_caps = ksz9477_get_caps,
- .fdb_dump = ksz9477_fdb_dump,
- .fdb_add = ksz9477_fdb_add,
- .fdb_del = ksz9477_fdb_del,
- .mdb_add = ksz9477_mdb_add,
- .mdb_del = ksz9477_mdb_del,
- .change_mtu = ksz9477_change_mtu,
- .max_mtu = ksz9477_max_mtu,
- .phylink_mac_link_up = ksz9477_phylink_mac_link_up,
- .config_cpu_port = ksz9477_config_cpu_port,
- .enable_stp_addr = ksz9477_enable_stp_addr,
- .reset = ksz9477_reset_switch,
- .init = ksz9477_switch_init,
- .exit = ksz9477_switch_exit,
- };
- static const struct ksz_dev_ops lan937x_dev_ops = {
- .setup = lan937x_setup,
- .teardown = lan937x_teardown,
- .get_port_addr = ksz9477_get_port_addr,
- .cfg_port_member = ksz9477_cfg_port_member,
- .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
- .port_setup = lan937x_port_setup,
- .set_ageing_time = lan937x_set_ageing_time,
- .r_phy = lan937x_r_phy,
- .w_phy = lan937x_w_phy,
- .r_mib_cnt = ksz9477_r_mib_cnt,
- .r_mib_pkt = ksz9477_r_mib_pkt,
- .r_mib_stat64 = ksz_r_mib_stats64,
- .freeze_mib = ksz9477_freeze_mib,
- .port_init_cnt = ksz9477_port_init_cnt,
- .vlan_filtering = ksz9477_port_vlan_filtering,
- .vlan_add = ksz9477_port_vlan_add,
- .vlan_del = ksz9477_port_vlan_del,
- .mirror_add = ksz9477_port_mirror_add,
- .mirror_del = ksz9477_port_mirror_del,
- .get_caps = lan937x_phylink_get_caps,
- .setup_rgmii_delay = lan937x_setup_rgmii_delay,
- .fdb_dump = ksz9477_fdb_dump,
- .fdb_add = ksz9477_fdb_add,
- .fdb_del = ksz9477_fdb_del,
- .mdb_add = ksz9477_mdb_add,
- .mdb_del = ksz9477_mdb_del,
- .change_mtu = lan937x_change_mtu,
- .max_mtu = ksz9477_max_mtu,
- .phylink_mac_link_up = ksz9477_phylink_mac_link_up,
- .config_cpu_port = lan937x_config_cpu_port,
- .enable_stp_addr = ksz9477_enable_stp_addr,
- .reset = lan937x_reset_switch,
- .init = lan937x_switch_init,
- .exit = lan937x_switch_exit,
- };
- static const u16 ksz8795_regs[] = {
- [REG_IND_CTRL_0] = 0x6E,
- [REG_IND_DATA_8] = 0x70,
- [REG_IND_DATA_CHECK] = 0x72,
- [REG_IND_DATA_HI] = 0x71,
- [REG_IND_DATA_LO] = 0x75,
- [REG_IND_MIB_CHECK] = 0x74,
- [REG_IND_BYTE] = 0xA0,
- [P_FORCE_CTRL] = 0x0C,
- [P_LINK_STATUS] = 0x0E,
- [P_LOCAL_CTRL] = 0x07,
- [P_NEG_RESTART_CTRL] = 0x0D,
- [P_REMOTE_STATUS] = 0x08,
- [P_SPEED_STATUS] = 0x09,
- [S_TAIL_TAG_CTRL] = 0x0C,
- [P_STP_CTRL] = 0x02,
- [S_START_CTRL] = 0x01,
- [S_BROADCAST_CTRL] = 0x06,
- [S_MULTICAST_CTRL] = 0x04,
- [P_XMII_CTRL_0] = 0x06,
- [P_XMII_CTRL_1] = 0x06,
- };
- static const u32 ksz8795_masks[] = {
- [PORT_802_1P_REMAPPING] = BIT(7),
- [SW_TAIL_TAG_ENABLE] = BIT(1),
- [MIB_COUNTER_OVERFLOW] = BIT(6),
- [MIB_COUNTER_VALID] = BIT(5),
- [VLAN_TABLE_FID] = GENMASK(6, 0),
- [VLAN_TABLE_MEMBERSHIP] = GENMASK(11, 7),
- [VLAN_TABLE_VALID] = BIT(12),
- [STATIC_MAC_TABLE_VALID] = BIT(21),
- [STATIC_MAC_TABLE_USE_FID] = BIT(23),
- [STATIC_MAC_TABLE_FID] = GENMASK(30, 24),
- [STATIC_MAC_TABLE_OVERRIDE] = BIT(22),
- [STATIC_MAC_TABLE_FWD_PORTS] = GENMASK(20, 16),
- [DYNAMIC_MAC_TABLE_ENTRIES_H] = GENMASK(6, 0),
- [DYNAMIC_MAC_TABLE_MAC_EMPTY] = BIT(7),
- [DYNAMIC_MAC_TABLE_NOT_READY] = BIT(7),
- [DYNAMIC_MAC_TABLE_ENTRIES] = GENMASK(31, 29),
- [DYNAMIC_MAC_TABLE_FID] = GENMASK(22, 16),
- [DYNAMIC_MAC_TABLE_SRC_PORT] = GENMASK(26, 24),
- [DYNAMIC_MAC_TABLE_TIMESTAMP] = GENMASK(28, 27),
- [P_MII_TX_FLOW_CTRL] = BIT(5),
- [P_MII_RX_FLOW_CTRL] = BIT(5),
- };
- static const u8 ksz8795_xmii_ctrl0[] = {
- [P_MII_100MBIT] = 0,
- [P_MII_10MBIT] = 1,
- [P_MII_FULL_DUPLEX] = 0,
- [P_MII_HALF_DUPLEX] = 1,
- };
- static const u8 ksz8795_xmii_ctrl1[] = {
- [P_RGMII_SEL] = 3,
- [P_GMII_SEL] = 2,
- [P_RMII_SEL] = 1,
- [P_MII_SEL] = 0,
- [P_GMII_1GBIT] = 1,
- [P_GMII_NOT_1GBIT] = 0,
- };
- static const u8 ksz8795_shifts[] = {
- [VLAN_TABLE_MEMBERSHIP_S] = 7,
- [VLAN_TABLE] = 16,
- [STATIC_MAC_FWD_PORTS] = 16,
- [STATIC_MAC_FID] = 24,
- [DYNAMIC_MAC_ENTRIES_H] = 3,
- [DYNAMIC_MAC_ENTRIES] = 29,
- [DYNAMIC_MAC_FID] = 16,
- [DYNAMIC_MAC_TIMESTAMP] = 27,
- [DYNAMIC_MAC_SRC_PORT] = 24,
- };
- static const u16 ksz8863_regs[] = {
- [REG_IND_CTRL_0] = 0x79,
- [REG_IND_DATA_8] = 0x7B,
- [REG_IND_DATA_CHECK] = 0x7B,
- [REG_IND_DATA_HI] = 0x7C,
- [REG_IND_DATA_LO] = 0x80,
- [REG_IND_MIB_CHECK] = 0x80,
- [P_FORCE_CTRL] = 0x0C,
- [P_LINK_STATUS] = 0x0E,
- [P_LOCAL_CTRL] = 0x0C,
- [P_NEG_RESTART_CTRL] = 0x0D,
- [P_REMOTE_STATUS] = 0x0E,
- [P_SPEED_STATUS] = 0x0F,
- [S_TAIL_TAG_CTRL] = 0x03,
- [P_STP_CTRL] = 0x02,
- [S_START_CTRL] = 0x01,
- [S_BROADCAST_CTRL] = 0x06,
- [S_MULTICAST_CTRL] = 0x04,
- };
- static const u32 ksz8863_masks[] = {
- [PORT_802_1P_REMAPPING] = BIT(3),
- [SW_TAIL_TAG_ENABLE] = BIT(6),
- [MIB_COUNTER_OVERFLOW] = BIT(7),
- [MIB_COUNTER_VALID] = BIT(6),
- [VLAN_TABLE_FID] = GENMASK(15, 12),
- [VLAN_TABLE_MEMBERSHIP] = GENMASK(18, 16),
- [VLAN_TABLE_VALID] = BIT(19),
- [STATIC_MAC_TABLE_VALID] = BIT(19),
- [STATIC_MAC_TABLE_USE_FID] = BIT(21),
- [STATIC_MAC_TABLE_FID] = GENMASK(25, 22),
- [STATIC_MAC_TABLE_OVERRIDE] = BIT(20),
- [STATIC_MAC_TABLE_FWD_PORTS] = GENMASK(18, 16),
- [DYNAMIC_MAC_TABLE_ENTRIES_H] = GENMASK(1, 0),
- [DYNAMIC_MAC_TABLE_MAC_EMPTY] = BIT(2),
- [DYNAMIC_MAC_TABLE_NOT_READY] = BIT(7),
- [DYNAMIC_MAC_TABLE_ENTRIES] = GENMASK(31, 24),
- [DYNAMIC_MAC_TABLE_FID] = GENMASK(19, 16),
- [DYNAMIC_MAC_TABLE_SRC_PORT] = GENMASK(21, 20),
- [DYNAMIC_MAC_TABLE_TIMESTAMP] = GENMASK(23, 22),
- };
- static u8 ksz8863_shifts[] = {
- [VLAN_TABLE_MEMBERSHIP_S] = 16,
- [STATIC_MAC_FWD_PORTS] = 16,
- [STATIC_MAC_FID] = 22,
- [DYNAMIC_MAC_ENTRIES_H] = 8,
- [DYNAMIC_MAC_ENTRIES] = 24,
- [DYNAMIC_MAC_FID] = 16,
- [DYNAMIC_MAC_TIMESTAMP] = 22,
- [DYNAMIC_MAC_SRC_PORT] = 20,
- };
- static const u16 ksz9477_regs[] = {
- [P_STP_CTRL] = 0x0B04,
- [S_START_CTRL] = 0x0300,
- [S_BROADCAST_CTRL] = 0x0332,
- [S_MULTICAST_CTRL] = 0x0331,
- [P_XMII_CTRL_0] = 0x0300,
- [P_XMII_CTRL_1] = 0x0301,
- };
- static const u32 ksz9477_masks[] = {
- [ALU_STAT_WRITE] = 0,
- [ALU_STAT_READ] = 1,
- [P_MII_TX_FLOW_CTRL] = BIT(5),
- [P_MII_RX_FLOW_CTRL] = BIT(3),
- };
- static const u8 ksz9477_shifts[] = {
- [ALU_STAT_INDEX] = 16,
- };
- static const u8 ksz9477_xmii_ctrl0[] = {
- [P_MII_100MBIT] = 1,
- [P_MII_10MBIT] = 0,
- [P_MII_FULL_DUPLEX] = 1,
- [P_MII_HALF_DUPLEX] = 0,
- };
- static const u8 ksz9477_xmii_ctrl1[] = {
- [P_RGMII_SEL] = 0,
- [P_RMII_SEL] = 1,
- [P_GMII_SEL] = 2,
- [P_MII_SEL] = 3,
- [P_GMII_1GBIT] = 0,
- [P_GMII_NOT_1GBIT] = 1,
- };
- static const u32 lan937x_masks[] = {
- [ALU_STAT_WRITE] = 1,
- [ALU_STAT_READ] = 2,
- [P_MII_TX_FLOW_CTRL] = BIT(5),
- [P_MII_RX_FLOW_CTRL] = BIT(3),
- };
- static const u8 lan937x_shifts[] = {
- [ALU_STAT_INDEX] = 8,
- };
- static const struct regmap_range ksz8563_valid_regs[] = {
- regmap_reg_range(0x0000, 0x0003),
- regmap_reg_range(0x0006, 0x0006),
- regmap_reg_range(0x000f, 0x001f),
- regmap_reg_range(0x0100, 0x0100),
- regmap_reg_range(0x0104, 0x0107),
- regmap_reg_range(0x010d, 0x010d),
- regmap_reg_range(0x0110, 0x0113),
- regmap_reg_range(0x0120, 0x012b),
- regmap_reg_range(0x0201, 0x0201),
- regmap_reg_range(0x0210, 0x0213),
- regmap_reg_range(0x0300, 0x0300),
- regmap_reg_range(0x0302, 0x031b),
- regmap_reg_range(0x0320, 0x032b),
- regmap_reg_range(0x0330, 0x0336),
- regmap_reg_range(0x0338, 0x033e),
- regmap_reg_range(0x0340, 0x035f),
- regmap_reg_range(0x0370, 0x0370),
- regmap_reg_range(0x0378, 0x0378),
- regmap_reg_range(0x037c, 0x037d),
- regmap_reg_range(0x0390, 0x0393),
- regmap_reg_range(0x0400, 0x040e),
- regmap_reg_range(0x0410, 0x042f),
- regmap_reg_range(0x0500, 0x0519),
- regmap_reg_range(0x0520, 0x054b),
- regmap_reg_range(0x0550, 0x05b3),
- /* port 1 */
- regmap_reg_range(0x1000, 0x1001),
- regmap_reg_range(0x1004, 0x100b),
- regmap_reg_range(0x1013, 0x1013),
- regmap_reg_range(0x1017, 0x1017),
- regmap_reg_range(0x101b, 0x101b),
- regmap_reg_range(0x101f, 0x1021),
- regmap_reg_range(0x1030, 0x1030),
- regmap_reg_range(0x1100, 0x1111),
- regmap_reg_range(0x111a, 0x111d),
- regmap_reg_range(0x1122, 0x1127),
- regmap_reg_range(0x112a, 0x112b),
- regmap_reg_range(0x1136, 0x1139),
- regmap_reg_range(0x113e, 0x113f),
- regmap_reg_range(0x1400, 0x1401),
- regmap_reg_range(0x1403, 0x1403),
- regmap_reg_range(0x1410, 0x1417),
- regmap_reg_range(0x1420, 0x1423),
- regmap_reg_range(0x1500, 0x1507),
- regmap_reg_range(0x1600, 0x1612),
- regmap_reg_range(0x1800, 0x180f),
- regmap_reg_range(0x1900, 0x1907),
- regmap_reg_range(0x1914, 0x191b),
- regmap_reg_range(0x1a00, 0x1a03),
- regmap_reg_range(0x1a04, 0x1a08),
- regmap_reg_range(0x1b00, 0x1b01),
- regmap_reg_range(0x1b04, 0x1b04),
- regmap_reg_range(0x1c00, 0x1c05),
- regmap_reg_range(0x1c08, 0x1c1b),
- /* port 2 */
- regmap_reg_range(0x2000, 0x2001),
- regmap_reg_range(0x2004, 0x200b),
- regmap_reg_range(0x2013, 0x2013),
- regmap_reg_range(0x2017, 0x2017),
- regmap_reg_range(0x201b, 0x201b),
- regmap_reg_range(0x201f, 0x2021),
- regmap_reg_range(0x2030, 0x2030),
- regmap_reg_range(0x2100, 0x2111),
- regmap_reg_range(0x211a, 0x211d),
- regmap_reg_range(0x2122, 0x2127),
- regmap_reg_range(0x212a, 0x212b),
- regmap_reg_range(0x2136, 0x2139),
- regmap_reg_range(0x213e, 0x213f),
- regmap_reg_range(0x2400, 0x2401),
- regmap_reg_range(0x2403, 0x2403),
- regmap_reg_range(0x2410, 0x2417),
- regmap_reg_range(0x2420, 0x2423),
- regmap_reg_range(0x2500, 0x2507),
- regmap_reg_range(0x2600, 0x2612),
- regmap_reg_range(0x2800, 0x280f),
- regmap_reg_range(0x2900, 0x2907),
- regmap_reg_range(0x2914, 0x291b),
- regmap_reg_range(0x2a00, 0x2a03),
- regmap_reg_range(0x2a04, 0x2a08),
- regmap_reg_range(0x2b00, 0x2b01),
- regmap_reg_range(0x2b04, 0x2b04),
- regmap_reg_range(0x2c00, 0x2c05),
- regmap_reg_range(0x2c08, 0x2c1b),
- /* port 3 */
- regmap_reg_range(0x3000, 0x3001),
- regmap_reg_range(0x3004, 0x300b),
- regmap_reg_range(0x3013, 0x3013),
- regmap_reg_range(0x3017, 0x3017),
- regmap_reg_range(0x301b, 0x301b),
- regmap_reg_range(0x301f, 0x3021),
- regmap_reg_range(0x3030, 0x3030),
- regmap_reg_range(0x3300, 0x3301),
- regmap_reg_range(0x3303, 0x3303),
- regmap_reg_range(0x3400, 0x3401),
- regmap_reg_range(0x3403, 0x3403),
- regmap_reg_range(0x3410, 0x3417),
- regmap_reg_range(0x3420, 0x3423),
- regmap_reg_range(0x3500, 0x3507),
- regmap_reg_range(0x3600, 0x3612),
- regmap_reg_range(0x3800, 0x380f),
- regmap_reg_range(0x3900, 0x3907),
- regmap_reg_range(0x3914, 0x391b),
- regmap_reg_range(0x3a00, 0x3a03),
- regmap_reg_range(0x3a04, 0x3a08),
- regmap_reg_range(0x3b00, 0x3b01),
- regmap_reg_range(0x3b04, 0x3b04),
- regmap_reg_range(0x3c00, 0x3c05),
- regmap_reg_range(0x3c08, 0x3c1b),
- };
- static const struct regmap_access_table ksz8563_register_set = {
- .yes_ranges = ksz8563_valid_regs,
- .n_yes_ranges = ARRAY_SIZE(ksz8563_valid_regs),
- };
- static const struct regmap_range ksz9477_valid_regs[] = {
- regmap_reg_range(0x0000, 0x0003),
- regmap_reg_range(0x0006, 0x0006),
- regmap_reg_range(0x0010, 0x001f),
- regmap_reg_range(0x0100, 0x0100),
- regmap_reg_range(0x0103, 0x0107),
- regmap_reg_range(0x010d, 0x010d),
- regmap_reg_range(0x0110, 0x0113),
- regmap_reg_range(0x0120, 0x012b),
- regmap_reg_range(0x0201, 0x0201),
- regmap_reg_range(0x0210, 0x0213),
- regmap_reg_range(0x0300, 0x0300),
- regmap_reg_range(0x0302, 0x031b),
- regmap_reg_range(0x0320, 0x032b),
- regmap_reg_range(0x0330, 0x0336),
- regmap_reg_range(0x0338, 0x033b),
- regmap_reg_range(0x033e, 0x033e),
- regmap_reg_range(0x0340, 0x035f),
- regmap_reg_range(0x0370, 0x0370),
- regmap_reg_range(0x0378, 0x0378),
- regmap_reg_range(0x037c, 0x037d),
- regmap_reg_range(0x0390, 0x0393),
- regmap_reg_range(0x0400, 0x040e),
- regmap_reg_range(0x0410, 0x042f),
- regmap_reg_range(0x0444, 0x044b),
- regmap_reg_range(0x0450, 0x046f),
- regmap_reg_range(0x0500, 0x0519),
- regmap_reg_range(0x0520, 0x054b),
- regmap_reg_range(0x0550, 0x05b3),
- regmap_reg_range(0x0604, 0x060b),
- regmap_reg_range(0x0610, 0x0612),
- regmap_reg_range(0x0614, 0x062c),
- regmap_reg_range(0x0640, 0x0645),
- regmap_reg_range(0x0648, 0x064d),
- /* port 1 */
- regmap_reg_range(0x1000, 0x1001),
- regmap_reg_range(0x1013, 0x1013),
- regmap_reg_range(0x1017, 0x1017),
- regmap_reg_range(0x101b, 0x101b),
- regmap_reg_range(0x101f, 0x1020),
- regmap_reg_range(0x1030, 0x1030),
- regmap_reg_range(0x1100, 0x1115),
- regmap_reg_range(0x111a, 0x111f),
- regmap_reg_range(0x1120, 0x112b),
- regmap_reg_range(0x1134, 0x113b),
- regmap_reg_range(0x113c, 0x113f),
- regmap_reg_range(0x1400, 0x1401),
- regmap_reg_range(0x1403, 0x1403),
- regmap_reg_range(0x1410, 0x1417),
- regmap_reg_range(0x1420, 0x1423),
- regmap_reg_range(0x1500, 0x1507),
- regmap_reg_range(0x1600, 0x1613),
- regmap_reg_range(0x1800, 0x180f),
- regmap_reg_range(0x1820, 0x1827),
- regmap_reg_range(0x1830, 0x1837),
- regmap_reg_range(0x1840, 0x184b),
- regmap_reg_range(0x1900, 0x1907),
- regmap_reg_range(0x1914, 0x191b),
- regmap_reg_range(0x1920, 0x1920),
- regmap_reg_range(0x1923, 0x1927),
- regmap_reg_range(0x1a00, 0x1a03),
- regmap_reg_range(0x1a04, 0x1a07),
- regmap_reg_range(0x1b00, 0x1b01),
- regmap_reg_range(0x1b04, 0x1b04),
- regmap_reg_range(0x1c00, 0x1c05),
- regmap_reg_range(0x1c08, 0x1c1b),
- /* port 2 */
- regmap_reg_range(0x2000, 0x2001),
- regmap_reg_range(0x2013, 0x2013),
- regmap_reg_range(0x2017, 0x2017),
- regmap_reg_range(0x201b, 0x201b),
- regmap_reg_range(0x201f, 0x2020),
- regmap_reg_range(0x2030, 0x2030),
- regmap_reg_range(0x2100, 0x2115),
- regmap_reg_range(0x211a, 0x211f),
- regmap_reg_range(0x2120, 0x212b),
- regmap_reg_range(0x2134, 0x213b),
- regmap_reg_range(0x213c, 0x213f),
- regmap_reg_range(0x2400, 0x2401),
- regmap_reg_range(0x2403, 0x2403),
- regmap_reg_range(0x2410, 0x2417),
- regmap_reg_range(0x2420, 0x2423),
- regmap_reg_range(0x2500, 0x2507),
- regmap_reg_range(0x2600, 0x2613),
- regmap_reg_range(0x2800, 0x280f),
- regmap_reg_range(0x2820, 0x2827),
- regmap_reg_range(0x2830, 0x2837),
- regmap_reg_range(0x2840, 0x284b),
- regmap_reg_range(0x2900, 0x2907),
- regmap_reg_range(0x2914, 0x291b),
- regmap_reg_range(0x2920, 0x2920),
- regmap_reg_range(0x2923, 0x2927),
- regmap_reg_range(0x2a00, 0x2a03),
- regmap_reg_range(0x2a04, 0x2a07),
- regmap_reg_range(0x2b00, 0x2b01),
- regmap_reg_range(0x2b04, 0x2b04),
- regmap_reg_range(0x2c00, 0x2c05),
- regmap_reg_range(0x2c08, 0x2c1b),
- /* port 3 */
- regmap_reg_range(0x3000, 0x3001),
- regmap_reg_range(0x3013, 0x3013),
- regmap_reg_range(0x3017, 0x3017),
- regmap_reg_range(0x301b, 0x301b),
- regmap_reg_range(0x301f, 0x3020),
- regmap_reg_range(0x3030, 0x3030),
- regmap_reg_range(0x3100, 0x3115),
- regmap_reg_range(0x311a, 0x311f),
- regmap_reg_range(0x3120, 0x312b),
- regmap_reg_range(0x3134, 0x313b),
- regmap_reg_range(0x313c, 0x313f),
- regmap_reg_range(0x3400, 0x3401),
- regmap_reg_range(0x3403, 0x3403),
- regmap_reg_range(0x3410, 0x3417),
- regmap_reg_range(0x3420, 0x3423),
- regmap_reg_range(0x3500, 0x3507),
- regmap_reg_range(0x3600, 0x3613),
- regmap_reg_range(0x3800, 0x380f),
- regmap_reg_range(0x3820, 0x3827),
- regmap_reg_range(0x3830, 0x3837),
- regmap_reg_range(0x3840, 0x384b),
- regmap_reg_range(0x3900, 0x3907),
- regmap_reg_range(0x3914, 0x391b),
- regmap_reg_range(0x3920, 0x3920),
- regmap_reg_range(0x3923, 0x3927),
- regmap_reg_range(0x3a00, 0x3a03),
- regmap_reg_range(0x3a04, 0x3a07),
- regmap_reg_range(0x3b00, 0x3b01),
- regmap_reg_range(0x3b04, 0x3b04),
- regmap_reg_range(0x3c00, 0x3c05),
- regmap_reg_range(0x3c08, 0x3c1b),
- /* port 4 */
- regmap_reg_range(0x4000, 0x4001),
- regmap_reg_range(0x4013, 0x4013),
- regmap_reg_range(0x4017, 0x4017),
- regmap_reg_range(0x401b, 0x401b),
- regmap_reg_range(0x401f, 0x4020),
- regmap_reg_range(0x4030, 0x4030),
- regmap_reg_range(0x4100, 0x4115),
- regmap_reg_range(0x411a, 0x411f),
- regmap_reg_range(0x4120, 0x412b),
- regmap_reg_range(0x4134, 0x413b),
- regmap_reg_range(0x413c, 0x413f),
- regmap_reg_range(0x4400, 0x4401),
- regmap_reg_range(0x4403, 0x4403),
- regmap_reg_range(0x4410, 0x4417),
- regmap_reg_range(0x4420, 0x4423),
- regmap_reg_range(0x4500, 0x4507),
- regmap_reg_range(0x4600, 0x4613),
- regmap_reg_range(0x4800, 0x480f),
- regmap_reg_range(0x4820, 0x4827),
- regmap_reg_range(0x4830, 0x4837),
- regmap_reg_range(0x4840, 0x484b),
- regmap_reg_range(0x4900, 0x4907),
- regmap_reg_range(0x4914, 0x491b),
- regmap_reg_range(0x4920, 0x4920),
- regmap_reg_range(0x4923, 0x4927),
- regmap_reg_range(0x4a00, 0x4a03),
- regmap_reg_range(0x4a04, 0x4a07),
- regmap_reg_range(0x4b00, 0x4b01),
- regmap_reg_range(0x4b04, 0x4b04),
- regmap_reg_range(0x4c00, 0x4c05),
- regmap_reg_range(0x4c08, 0x4c1b),
- /* port 5 */
- regmap_reg_range(0x5000, 0x5001),
- regmap_reg_range(0x5013, 0x5013),
- regmap_reg_range(0x5017, 0x5017),
- regmap_reg_range(0x501b, 0x501b),
- regmap_reg_range(0x501f, 0x5020),
- regmap_reg_range(0x5030, 0x5030),
- regmap_reg_range(0x5100, 0x5115),
- regmap_reg_range(0x511a, 0x511f),
- regmap_reg_range(0x5120, 0x512b),
- regmap_reg_range(0x5134, 0x513b),
- regmap_reg_range(0x513c, 0x513f),
- regmap_reg_range(0x5400, 0x5401),
- regmap_reg_range(0x5403, 0x5403),
- regmap_reg_range(0x5410, 0x5417),
- regmap_reg_range(0x5420, 0x5423),
- regmap_reg_range(0x5500, 0x5507),
- regmap_reg_range(0x5600, 0x5613),
- regmap_reg_range(0x5800, 0x580f),
- regmap_reg_range(0x5820, 0x5827),
- regmap_reg_range(0x5830, 0x5837),
- regmap_reg_range(0x5840, 0x584b),
- regmap_reg_range(0x5900, 0x5907),
- regmap_reg_range(0x5914, 0x591b),
- regmap_reg_range(0x5920, 0x5920),
- regmap_reg_range(0x5923, 0x5927),
- regmap_reg_range(0x5a00, 0x5a03),
- regmap_reg_range(0x5a04, 0x5a07),
- regmap_reg_range(0x5b00, 0x5b01),
- regmap_reg_range(0x5b04, 0x5b04),
- regmap_reg_range(0x5c00, 0x5c05),
- regmap_reg_range(0x5c08, 0x5c1b),
- /* port 6 */
- regmap_reg_range(0x6000, 0x6001),
- regmap_reg_range(0x6013, 0x6013),
- regmap_reg_range(0x6017, 0x6017),
- regmap_reg_range(0x601b, 0x601b),
- regmap_reg_range(0x601f, 0x6020),
- regmap_reg_range(0x6030, 0x6030),
- regmap_reg_range(0x6300, 0x6301),
- regmap_reg_range(0x6400, 0x6401),
- regmap_reg_range(0x6403, 0x6403),
- regmap_reg_range(0x6410, 0x6417),
- regmap_reg_range(0x6420, 0x6423),
- regmap_reg_range(0x6500, 0x6507),
- regmap_reg_range(0x6600, 0x6613),
- regmap_reg_range(0x6800, 0x680f),
- regmap_reg_range(0x6820, 0x6827),
- regmap_reg_range(0x6830, 0x6837),
- regmap_reg_range(0x6840, 0x684b),
- regmap_reg_range(0x6900, 0x6907),
- regmap_reg_range(0x6914, 0x691b),
- regmap_reg_range(0x6920, 0x6920),
- regmap_reg_range(0x6923, 0x6927),
- regmap_reg_range(0x6a00, 0x6a03),
- regmap_reg_range(0x6a04, 0x6a07),
- regmap_reg_range(0x6b00, 0x6b01),
- regmap_reg_range(0x6b04, 0x6b04),
- regmap_reg_range(0x6c00, 0x6c05),
- regmap_reg_range(0x6c08, 0x6c1b),
- /* port 7 */
- regmap_reg_range(0x7000, 0x7001),
- regmap_reg_range(0x7013, 0x7013),
- regmap_reg_range(0x7017, 0x7017),
- regmap_reg_range(0x701b, 0x701b),
- regmap_reg_range(0x701f, 0x7020),
- regmap_reg_range(0x7030, 0x7030),
- regmap_reg_range(0x7200, 0x7203),
- regmap_reg_range(0x7206, 0x7207),
- regmap_reg_range(0x7300, 0x7301),
- regmap_reg_range(0x7400, 0x7401),
- regmap_reg_range(0x7403, 0x7403),
- regmap_reg_range(0x7410, 0x7417),
- regmap_reg_range(0x7420, 0x7423),
- regmap_reg_range(0x7500, 0x7507),
- regmap_reg_range(0x7600, 0x7613),
- regmap_reg_range(0x7800, 0x780f),
- regmap_reg_range(0x7820, 0x7827),
- regmap_reg_range(0x7830, 0x7837),
- regmap_reg_range(0x7840, 0x784b),
- regmap_reg_range(0x7900, 0x7907),
- regmap_reg_range(0x7914, 0x791b),
- regmap_reg_range(0x7920, 0x7920),
- regmap_reg_range(0x7923, 0x7927),
- regmap_reg_range(0x7a00, 0x7a03),
- regmap_reg_range(0x7a04, 0x7a07),
- regmap_reg_range(0x7b00, 0x7b01),
- regmap_reg_range(0x7b04, 0x7b04),
- regmap_reg_range(0x7c00, 0x7c05),
- regmap_reg_range(0x7c08, 0x7c1b),
- };
- static const struct regmap_access_table ksz9477_register_set = {
- .yes_ranges = ksz9477_valid_regs,
- .n_yes_ranges = ARRAY_SIZE(ksz9477_valid_regs),
- };
- static const struct regmap_range ksz9896_valid_regs[] = {
- regmap_reg_range(0x0000, 0x0003),
- regmap_reg_range(0x0006, 0x0006),
- regmap_reg_range(0x0010, 0x001f),
- regmap_reg_range(0x0100, 0x0100),
- regmap_reg_range(0x0103, 0x0107),
- regmap_reg_range(0x010d, 0x010d),
- regmap_reg_range(0x0110, 0x0113),
- regmap_reg_range(0x0120, 0x0127),
- regmap_reg_range(0x0201, 0x0201),
- regmap_reg_range(0x0210, 0x0213),
- regmap_reg_range(0x0300, 0x0300),
- regmap_reg_range(0x0302, 0x030b),
- regmap_reg_range(0x0310, 0x031b),
- regmap_reg_range(0x0320, 0x032b),
- regmap_reg_range(0x0330, 0x0336),
- regmap_reg_range(0x0338, 0x033b),
- regmap_reg_range(0x033e, 0x033e),
- regmap_reg_range(0x0340, 0x035f),
- regmap_reg_range(0x0370, 0x0370),
- regmap_reg_range(0x0378, 0x0378),
- regmap_reg_range(0x037c, 0x037d),
- regmap_reg_range(0x0390, 0x0393),
- regmap_reg_range(0x0400, 0x040e),
- regmap_reg_range(0x0410, 0x042f),
- /* port 1 */
- regmap_reg_range(0x1000, 0x1001),
- regmap_reg_range(0x1013, 0x1013),
- regmap_reg_range(0x1017, 0x1017),
- regmap_reg_range(0x101b, 0x101b),
- regmap_reg_range(0x101f, 0x1020),
- regmap_reg_range(0x1030, 0x1030),
- regmap_reg_range(0x1100, 0x1115),
- regmap_reg_range(0x111a, 0x111f),
- regmap_reg_range(0x1122, 0x1127),
- regmap_reg_range(0x112a, 0x112b),
- regmap_reg_range(0x1136, 0x1139),
- regmap_reg_range(0x113e, 0x113f),
- regmap_reg_range(0x1400, 0x1401),
- regmap_reg_range(0x1403, 0x1403),
- regmap_reg_range(0x1410, 0x1417),
- regmap_reg_range(0x1420, 0x1423),
- regmap_reg_range(0x1500, 0x1507),
- regmap_reg_range(0x1600, 0x1612),
- regmap_reg_range(0x1800, 0x180f),
- regmap_reg_range(0x1820, 0x1827),
- regmap_reg_range(0x1830, 0x1837),
- regmap_reg_range(0x1840, 0x184b),
- regmap_reg_range(0x1900, 0x1907),
- regmap_reg_range(0x1914, 0x1915),
- regmap_reg_range(0x1a00, 0x1a03),
- regmap_reg_range(0x1a04, 0x1a07),
- regmap_reg_range(0x1b00, 0x1b01),
- regmap_reg_range(0x1b04, 0x1b04),
- /* port 2 */
- regmap_reg_range(0x2000, 0x2001),
- regmap_reg_range(0x2013, 0x2013),
- regmap_reg_range(0x2017, 0x2017),
- regmap_reg_range(0x201b, 0x201b),
- regmap_reg_range(0x201f, 0x2020),
- regmap_reg_range(0x2030, 0x2030),
- regmap_reg_range(0x2100, 0x2115),
- regmap_reg_range(0x211a, 0x211f),
- regmap_reg_range(0x2122, 0x2127),
- regmap_reg_range(0x212a, 0x212b),
- regmap_reg_range(0x2136, 0x2139),
- regmap_reg_range(0x213e, 0x213f),
- regmap_reg_range(0x2400, 0x2401),
- regmap_reg_range(0x2403, 0x2403),
- regmap_reg_range(0x2410, 0x2417),
- regmap_reg_range(0x2420, 0x2423),
- regmap_reg_range(0x2500, 0x2507),
- regmap_reg_range(0x2600, 0x2612),
- regmap_reg_range(0x2800, 0x280f),
- regmap_reg_range(0x2820, 0x2827),
- regmap_reg_range(0x2830, 0x2837),
- regmap_reg_range(0x2840, 0x284b),
- regmap_reg_range(0x2900, 0x2907),
- regmap_reg_range(0x2914, 0x2915),
- regmap_reg_range(0x2a00, 0x2a03),
- regmap_reg_range(0x2a04, 0x2a07),
- regmap_reg_range(0x2b00, 0x2b01),
- regmap_reg_range(0x2b04, 0x2b04),
- /* port 3 */
- regmap_reg_range(0x3000, 0x3001),
- regmap_reg_range(0x3013, 0x3013),
- regmap_reg_range(0x3017, 0x3017),
- regmap_reg_range(0x301b, 0x301b),
- regmap_reg_range(0x301f, 0x3020),
- regmap_reg_range(0x3030, 0x3030),
- regmap_reg_range(0x3100, 0x3115),
- regmap_reg_range(0x311a, 0x311f),
- regmap_reg_range(0x3122, 0x3127),
- regmap_reg_range(0x312a, 0x312b),
- regmap_reg_range(0x3136, 0x3139),
- regmap_reg_range(0x313e, 0x313f),
- regmap_reg_range(0x3400, 0x3401),
- regmap_reg_range(0x3403, 0x3403),
- regmap_reg_range(0x3410, 0x3417),
- regmap_reg_range(0x3420, 0x3423),
- regmap_reg_range(0x3500, 0x3507),
- regmap_reg_range(0x3600, 0x3612),
- regmap_reg_range(0x3800, 0x380f),
- regmap_reg_range(0x3820, 0x3827),
- regmap_reg_range(0x3830, 0x3837),
- regmap_reg_range(0x3840, 0x384b),
- regmap_reg_range(0x3900, 0x3907),
- regmap_reg_range(0x3914, 0x3915),
- regmap_reg_range(0x3a00, 0x3a03),
- regmap_reg_range(0x3a04, 0x3a07),
- regmap_reg_range(0x3b00, 0x3b01),
- regmap_reg_range(0x3b04, 0x3b04),
- /* port 4 */
- regmap_reg_range(0x4000, 0x4001),
- regmap_reg_range(0x4013, 0x4013),
- regmap_reg_range(0x4017, 0x4017),
- regmap_reg_range(0x401b, 0x401b),
- regmap_reg_range(0x401f, 0x4020),
- regmap_reg_range(0x4030, 0x4030),
- regmap_reg_range(0x4100, 0x4115),
- regmap_reg_range(0x411a, 0x411f),
- regmap_reg_range(0x4122, 0x4127),
- regmap_reg_range(0x412a, 0x412b),
- regmap_reg_range(0x4136, 0x4139),
- regmap_reg_range(0x413e, 0x413f),
- regmap_reg_range(0x4400, 0x4401),
- regmap_reg_range(0x4403, 0x4403),
- regmap_reg_range(0x4410, 0x4417),
- regmap_reg_range(0x4420, 0x4423),
- regmap_reg_range(0x4500, 0x4507),
- regmap_reg_range(0x4600, 0x4612),
- regmap_reg_range(0x4800, 0x480f),
- regmap_reg_range(0x4820, 0x4827),
- regmap_reg_range(0x4830, 0x4837),
- regmap_reg_range(0x4840, 0x484b),
- regmap_reg_range(0x4900, 0x4907),
- regmap_reg_range(0x4914, 0x4915),
- regmap_reg_range(0x4a00, 0x4a03),
- regmap_reg_range(0x4a04, 0x4a07),
- regmap_reg_range(0x4b00, 0x4b01),
- regmap_reg_range(0x4b04, 0x4b04),
- /* port 5 */
- regmap_reg_range(0x5000, 0x5001),
- regmap_reg_range(0x5013, 0x5013),
- regmap_reg_range(0x5017, 0x5017),
- regmap_reg_range(0x501b, 0x501b),
- regmap_reg_range(0x501f, 0x5020),
- regmap_reg_range(0x5030, 0x5030),
- regmap_reg_range(0x5100, 0x5115),
- regmap_reg_range(0x511a, 0x511f),
- regmap_reg_range(0x5122, 0x5127),
- regmap_reg_range(0x512a, 0x512b),
- regmap_reg_range(0x5136, 0x5139),
- regmap_reg_range(0x513e, 0x513f),
- regmap_reg_range(0x5400, 0x5401),
- regmap_reg_range(0x5403, 0x5403),
- regmap_reg_range(0x5410, 0x5417),
- regmap_reg_range(0x5420, 0x5423),
- regmap_reg_range(0x5500, 0x5507),
- regmap_reg_range(0x5600, 0x5612),
- regmap_reg_range(0x5800, 0x580f),
- regmap_reg_range(0x5820, 0x5827),
- regmap_reg_range(0x5830, 0x5837),
- regmap_reg_range(0x5840, 0x584b),
- regmap_reg_range(0x5900, 0x5907),
- regmap_reg_range(0x5914, 0x5915),
- regmap_reg_range(0x5a00, 0x5a03),
- regmap_reg_range(0x5a04, 0x5a07),
- regmap_reg_range(0x5b00, 0x5b01),
- regmap_reg_range(0x5b04, 0x5b04),
- /* port 6 */
- regmap_reg_range(0x6000, 0x6001),
- regmap_reg_range(0x6013, 0x6013),
- regmap_reg_range(0x6017, 0x6017),
- regmap_reg_range(0x601b, 0x601b),
- regmap_reg_range(0x601f, 0x6020),
- regmap_reg_range(0x6030, 0x6030),
- regmap_reg_range(0x6100, 0x6115),
- regmap_reg_range(0x611a, 0x611f),
- regmap_reg_range(0x6122, 0x6127),
- regmap_reg_range(0x612a, 0x612b),
- regmap_reg_range(0x6136, 0x6139),
- regmap_reg_range(0x613e, 0x613f),
- regmap_reg_range(0x6300, 0x6301),
- regmap_reg_range(0x6400, 0x6401),
- regmap_reg_range(0x6403, 0x6403),
- regmap_reg_range(0x6410, 0x6417),
- regmap_reg_range(0x6420, 0x6423),
- regmap_reg_range(0x6500, 0x6507),
- regmap_reg_range(0x6600, 0x6612),
- regmap_reg_range(0x6800, 0x680f),
- regmap_reg_range(0x6820, 0x6827),
- regmap_reg_range(0x6830, 0x6837),
- regmap_reg_range(0x6840, 0x684b),
- regmap_reg_range(0x6900, 0x6907),
- regmap_reg_range(0x6914, 0x6915),
- regmap_reg_range(0x6a00, 0x6a03),
- regmap_reg_range(0x6a04, 0x6a07),
- regmap_reg_range(0x6b00, 0x6b01),
- regmap_reg_range(0x6b04, 0x6b04),
- };
- static const struct regmap_access_table ksz9896_register_set = {
- .yes_ranges = ksz9896_valid_regs,
- .n_yes_ranges = ARRAY_SIZE(ksz9896_valid_regs),
- };
- const struct ksz_chip_data ksz_switch_chips[] = {
- [KSZ8563] = {
- .chip_id = KSZ8563_CHIP_ID,
- .dev_name = "KSZ8563",
- .num_vlans = 4096,
- .num_alus = 4096,
- .num_statics = 16,
- .cpu_ports = 0x07, /* can be configured as cpu port */
- .port_cnt = 3, /* total port count */
- .ops = &ksz9477_dev_ops,
- .mib_names = ksz9477_mib_names,
- .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
- .reg_mib_cnt = MIB_COUNTER_NUM,
- .regs = ksz9477_regs,
- .masks = ksz9477_masks,
- .shifts = ksz9477_shifts,
- .xmii_ctrl0 = ksz9477_xmii_ctrl0,
- .xmii_ctrl1 = ksz8795_xmii_ctrl1, /* Same as ksz8795 */
- .supports_mii = {false, false, true},
- .supports_rmii = {false, false, true},
- .supports_rgmii = {false, false, true},
- .internal_phy = {true, true, false},
- .gbit_capable = {false, false, true},
- .wr_table = &ksz8563_register_set,
- .rd_table = &ksz8563_register_set,
- },
- [KSZ8795] = {
- .chip_id = KSZ8795_CHIP_ID,
- .dev_name = "KSZ8795",
- .num_vlans = 4096,
- .num_alus = 0,
- .num_statics = 8,
- .cpu_ports = 0x10, /* can be configured as cpu port */
- .port_cnt = 5, /* total cpu and user ports */
- .ops = &ksz8_dev_ops,
- .ksz87xx_eee_link_erratum = true,
- .mib_names = ksz9477_mib_names,
- .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
- .reg_mib_cnt = MIB_COUNTER_NUM,
- .regs = ksz8795_regs,
- .masks = ksz8795_masks,
- .shifts = ksz8795_shifts,
- .xmii_ctrl0 = ksz8795_xmii_ctrl0,
- .xmii_ctrl1 = ksz8795_xmii_ctrl1,
- .supports_mii = {false, false, false, false, true},
- .supports_rmii = {false, false, false, false, true},
- .supports_rgmii = {false, false, false, false, true},
- .internal_phy = {true, true, true, true, false},
- },
- [KSZ8794] = {
- /* WARNING
- * =======
- * KSZ8794 is similar to KSZ8795, except the port map
- * contains a gap between external and CPU ports, the
- * port map is NOT continuous. The per-port register
- * map is shifted accordingly too, i.e. registers at
- * offset 0x40 are NOT used on KSZ8794 and they ARE
- * used on KSZ8795 for external port 3.
- * external cpu
- * KSZ8794 0,1,2 4
- * KSZ8795 0,1,2,3 4
- * KSZ8765 0,1,2,3 4
- * port_cnt is configured as 5, even though it is 4
- */
- .chip_id = KSZ8794_CHIP_ID,
- .dev_name = "KSZ8794",
- .num_vlans = 4096,
- .num_alus = 0,
- .num_statics = 8,
- .cpu_ports = 0x10, /* can be configured as cpu port */
- .port_cnt = 5, /* total cpu and user ports */
- .ops = &ksz8_dev_ops,
- .ksz87xx_eee_link_erratum = true,
- .mib_names = ksz9477_mib_names,
- .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
- .reg_mib_cnt = MIB_COUNTER_NUM,
- .regs = ksz8795_regs,
- .masks = ksz8795_masks,
- .shifts = ksz8795_shifts,
- .xmii_ctrl0 = ksz8795_xmii_ctrl0,
- .xmii_ctrl1 = ksz8795_xmii_ctrl1,
- .supports_mii = {false, false, false, false, true},
- .supports_rmii = {false, false, false, false, true},
- .supports_rgmii = {false, false, false, false, true},
- .internal_phy = {true, true, true, false, false},
- },
- [KSZ8765] = {
- .chip_id = KSZ8765_CHIP_ID,
- .dev_name = "KSZ8765",
- .num_vlans = 4096,
- .num_alus = 0,
- .num_statics = 8,
- .cpu_ports = 0x10, /* can be configured as cpu port */
- .port_cnt = 5, /* total cpu and user ports */
- .ops = &ksz8_dev_ops,
- .ksz87xx_eee_link_erratum = true,
- .mib_names = ksz9477_mib_names,
- .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
- .reg_mib_cnt = MIB_COUNTER_NUM,
- .regs = ksz8795_regs,
- .masks = ksz8795_masks,
- .shifts = ksz8795_shifts,
- .xmii_ctrl0 = ksz8795_xmii_ctrl0,
- .xmii_ctrl1 = ksz8795_xmii_ctrl1,
- .supports_mii = {false, false, false, false, true},
- .supports_rmii = {false, false, false, false, true},
- .supports_rgmii = {false, false, false, false, true},
- .internal_phy = {true, true, true, true, false},
- },
- [KSZ8830] = {
- .chip_id = KSZ8830_CHIP_ID,
- .dev_name = "KSZ8863/KSZ8873",
- .num_vlans = 16,
- .num_alus = 0,
- .num_statics = 8,
- .cpu_ports = 0x4, /* can be configured as cpu port */
- .port_cnt = 3,
- .ops = &ksz8_dev_ops,
- .mib_names = ksz88xx_mib_names,
- .mib_cnt = ARRAY_SIZE(ksz88xx_mib_names),
- .reg_mib_cnt = MIB_COUNTER_NUM,
- .regs = ksz8863_regs,
- .masks = ksz8863_masks,
- .shifts = ksz8863_shifts,
- .supports_mii = {false, false, true},
- .supports_rmii = {false, false, true},
- .internal_phy = {true, true, false},
- },
- [KSZ9477] = {
- .chip_id = KSZ9477_CHIP_ID,
- .dev_name = "KSZ9477",
- .num_vlans = 4096,
- .num_alus = 4096,
- .num_statics = 16,
- .cpu_ports = 0x7F, /* can be configured as cpu port */
- .port_cnt = 7, /* total physical port count */
- .port_nirqs = 4,
- .ops = &ksz9477_dev_ops,
- .phy_errata_9477 = true,
- .mib_names = ksz9477_mib_names,
- .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
- .reg_mib_cnt = MIB_COUNTER_NUM,
- .regs = ksz9477_regs,
- .masks = ksz9477_masks,
- .shifts = ksz9477_shifts,
- .xmii_ctrl0 = ksz9477_xmii_ctrl0,
- .xmii_ctrl1 = ksz9477_xmii_ctrl1,
- .supports_mii = {false, false, false, false,
- false, true, false},
- .supports_rmii = {false, false, false, false,
- false, true, false},
- .supports_rgmii = {false, false, false, false,
- false, true, false},
- .internal_phy = {true, true, true, true,
- true, false, false},
- .gbit_capable = {true, true, true, true, true, true, true},
- .wr_table = &ksz9477_register_set,
- .rd_table = &ksz9477_register_set,
- },
- [KSZ9896] = {
- .chip_id = KSZ9896_CHIP_ID,
- .dev_name = "KSZ9896",
- .num_vlans = 4096,
- .num_alus = 4096,
- .num_statics = 16,
- .cpu_ports = 0x3F, /* can be configured as cpu port */
- .port_cnt = 6, /* total physical port count */
- .port_nirqs = 2,
- .ops = &ksz9477_dev_ops,
- .phy_errata_9477 = true,
- .mib_names = ksz9477_mib_names,
- .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
- .reg_mib_cnt = MIB_COUNTER_NUM,
- .regs = ksz9477_regs,
- .masks = ksz9477_masks,
- .shifts = ksz9477_shifts,
- .xmii_ctrl0 = ksz9477_xmii_ctrl0,
- .xmii_ctrl1 = ksz9477_xmii_ctrl1,
- .supports_mii = {false, false, false, false,
- false, true},
- .supports_rmii = {false, false, false, false,
- false, true},
- .supports_rgmii = {false, false, false, false,
- false, true},
- .internal_phy = {true, true, true, true,
- true, false},
- .gbit_capable = {true, true, true, true, true, true},
- .wr_table = &ksz9896_register_set,
- .rd_table = &ksz9896_register_set,
- },
- [KSZ9897] = {
- .chip_id = KSZ9897_CHIP_ID,
- .dev_name = "KSZ9897",
- .num_vlans = 4096,
- .num_alus = 4096,
- .num_statics = 16,
- .cpu_ports = 0x7F, /* can be configured as cpu port */
- .port_cnt = 7, /* total physical port count */
- .port_nirqs = 2,
- .ops = &ksz9477_dev_ops,
- .phy_errata_9477 = true,
- .mib_names = ksz9477_mib_names,
- .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
- .reg_mib_cnt = MIB_COUNTER_NUM,
- .regs = ksz9477_regs,
- .masks = ksz9477_masks,
- .shifts = ksz9477_shifts,
- .xmii_ctrl0 = ksz9477_xmii_ctrl0,
- .xmii_ctrl1 = ksz9477_xmii_ctrl1,
- .supports_mii = {false, false, false, false,
- false, true, true},
- .supports_rmii = {false, false, false, false,
- false, true, true},
- .supports_rgmii = {false, false, false, false,
- false, true, true},
- .internal_phy = {true, true, true, true,
- true, false, false},
- .gbit_capable = {true, true, true, true, true, true, true},
- },
- [KSZ9893] = {
- .chip_id = KSZ9893_CHIP_ID,
- .dev_name = "KSZ9893",
- .num_vlans = 4096,
- .num_alus = 4096,
- .num_statics = 16,
- .cpu_ports = 0x07, /* can be configured as cpu port */
- .port_cnt = 3, /* total port count */
- .port_nirqs = 2,
- .ops = &ksz9477_dev_ops,
- .mib_names = ksz9477_mib_names,
- .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
- .reg_mib_cnt = MIB_COUNTER_NUM,
- .regs = ksz9477_regs,
- .masks = ksz9477_masks,
- .shifts = ksz9477_shifts,
- .xmii_ctrl0 = ksz9477_xmii_ctrl0,
- .xmii_ctrl1 = ksz8795_xmii_ctrl1, /* Same as ksz8795 */
- .supports_mii = {false, false, true},
- .supports_rmii = {false, false, true},
- .supports_rgmii = {false, false, true},
- .internal_phy = {true, true, false},
- .gbit_capable = {true, true, true},
- },
- [KSZ9567] = {
- .chip_id = KSZ9567_CHIP_ID,
- .dev_name = "KSZ9567",
- .num_vlans = 4096,
- .num_alus = 4096,
- .num_statics = 16,
- .cpu_ports = 0x7F, /* can be configured as cpu port */
- .port_cnt = 7, /* total physical port count */
- .port_nirqs = 3,
- .ops = &ksz9477_dev_ops,
- .phy_errata_9477 = true,
- .mib_names = ksz9477_mib_names,
- .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
- .reg_mib_cnt = MIB_COUNTER_NUM,
- .regs = ksz9477_regs,
- .masks = ksz9477_masks,
- .shifts = ksz9477_shifts,
- .xmii_ctrl0 = ksz9477_xmii_ctrl0,
- .xmii_ctrl1 = ksz9477_xmii_ctrl1,
- .supports_mii = {false, false, false, false,
- false, true, true},
- .supports_rmii = {false, false, false, false,
- false, true, true},
- .supports_rgmii = {false, false, false, false,
- false, true, true},
- .internal_phy = {true, true, true, true,
- true, false, false},
- .gbit_capable = {true, true, true, true, true, true, true},
- },
- [LAN9370] = {
- .chip_id = LAN9370_CHIP_ID,
- .dev_name = "LAN9370",
- .num_vlans = 4096,
- .num_alus = 1024,
- .num_statics = 256,
- .cpu_ports = 0x10, /* can be configured as cpu port */
- .port_cnt = 5, /* total physical port count */
- .port_nirqs = 6,
- .ops = &lan937x_dev_ops,
- .mib_names = ksz9477_mib_names,
- .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
- .reg_mib_cnt = MIB_COUNTER_NUM,
- .regs = ksz9477_regs,
- .masks = lan937x_masks,
- .shifts = lan937x_shifts,
- .xmii_ctrl0 = ksz9477_xmii_ctrl0,
- .xmii_ctrl1 = ksz9477_xmii_ctrl1,
- .supports_mii = {false, false, false, false, true},
- .supports_rmii = {false, false, false, false, true},
- .supports_rgmii = {false, false, false, false, true},
- .internal_phy = {true, true, true, true, false},
- },
- [LAN9371] = {
- .chip_id = LAN9371_CHIP_ID,
- .dev_name = "LAN9371",
- .num_vlans = 4096,
- .num_alus = 1024,
- .num_statics = 256,
- .cpu_ports = 0x30, /* can be configured as cpu port */
- .port_cnt = 6, /* total physical port count */
- .port_nirqs = 6,
- .ops = &lan937x_dev_ops,
- .mib_names = ksz9477_mib_names,
- .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
- .reg_mib_cnt = MIB_COUNTER_NUM,
- .regs = ksz9477_regs,
- .masks = lan937x_masks,
- .shifts = lan937x_shifts,
- .xmii_ctrl0 = ksz9477_xmii_ctrl0,
- .xmii_ctrl1 = ksz9477_xmii_ctrl1,
- .supports_mii = {false, false, false, false, true, true},
- .supports_rmii = {false, false, false, false, true, true},
- .supports_rgmii = {false, false, false, false, true, true},
- .internal_phy = {true, true, true, true, false, false},
- },
- [LAN9372] = {
- .chip_id = LAN9372_CHIP_ID,
- .dev_name = "LAN9372",
- .num_vlans = 4096,
- .num_alus = 1024,
- .num_statics = 256,
- .cpu_ports = 0x30, /* can be configured as cpu port */
- .port_cnt = 8, /* total physical port count */
- .port_nirqs = 6,
- .ops = &lan937x_dev_ops,
- .mib_names = ksz9477_mib_names,
- .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
- .reg_mib_cnt = MIB_COUNTER_NUM,
- .regs = ksz9477_regs,
- .masks = lan937x_masks,
- .shifts = lan937x_shifts,
- .xmii_ctrl0 = ksz9477_xmii_ctrl0,
- .xmii_ctrl1 = ksz9477_xmii_ctrl1,
- .supports_mii = {false, false, false, false,
- true, true, false, false},
- .supports_rmii = {false, false, false, false,
- true, true, false, false},
- .supports_rgmii = {false, false, false, false,
- true, true, false, false},
- .internal_phy = {true, true, true, true,
- false, false, true, true},
- },
- [LAN9373] = {
- .chip_id = LAN9373_CHIP_ID,
- .dev_name = "LAN9373",
- .num_vlans = 4096,
- .num_alus = 1024,
- .num_statics = 256,
- .cpu_ports = 0x38, /* can be configured as cpu port */
- .port_cnt = 5, /* total physical port count */
- .port_nirqs = 6,
- .ops = &lan937x_dev_ops,
- .mib_names = ksz9477_mib_names,
- .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
- .reg_mib_cnt = MIB_COUNTER_NUM,
- .regs = ksz9477_regs,
- .masks = lan937x_masks,
- .shifts = lan937x_shifts,
- .xmii_ctrl0 = ksz9477_xmii_ctrl0,
- .xmii_ctrl1 = ksz9477_xmii_ctrl1,
- .supports_mii = {false, false, false, false,
- true, true, false, false},
- .supports_rmii = {false, false, false, false,
- true, true, false, false},
- .supports_rgmii = {false, false, false, false,
- true, true, false, false},
- .internal_phy = {true, true, true, false,
- false, false, true, true},
- },
- [LAN9374] = {
- .chip_id = LAN9374_CHIP_ID,
- .dev_name = "LAN9374",
- .num_vlans = 4096,
- .num_alus = 1024,
- .num_statics = 256,
- .cpu_ports = 0x30, /* can be configured as cpu port */
- .port_cnt = 8, /* total physical port count */
- .port_nirqs = 6,
- .ops = &lan937x_dev_ops,
- .mib_names = ksz9477_mib_names,
- .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
- .reg_mib_cnt = MIB_COUNTER_NUM,
- .regs = ksz9477_regs,
- .masks = lan937x_masks,
- .shifts = lan937x_shifts,
- .xmii_ctrl0 = ksz9477_xmii_ctrl0,
- .xmii_ctrl1 = ksz9477_xmii_ctrl1,
- .supports_mii = {false, false, false, false,
- true, true, false, false},
- .supports_rmii = {false, false, false, false,
- true, true, false, false},
- .supports_rgmii = {false, false, false, false,
- true, true, false, false},
- .internal_phy = {true, true, true, true,
- false, false, true, true},
- },
- };
- EXPORT_SYMBOL_GPL(ksz_switch_chips);
- static const struct ksz_chip_data *ksz_lookup_info(unsigned int prod_num)
- {
- int i;
- for (i = 0; i < ARRAY_SIZE(ksz_switch_chips); i++) {
- const struct ksz_chip_data *chip = &ksz_switch_chips[i];
- if (chip->chip_id == prod_num)
- return chip;
- }
- return NULL;
- }
- static int ksz_check_device_id(struct ksz_device *dev)
- {
- const struct ksz_chip_data *dt_chip_data;
- dt_chip_data = of_device_get_match_data(dev->dev);
- /* Check for Device Tree and Chip ID */
- if (dt_chip_data->chip_id != dev->chip_id) {
- dev_err(dev->dev,
- "Device tree specifies chip %s but found %s, please fix it!\n",
- dt_chip_data->dev_name, dev->info->dev_name);
- return -ENODEV;
- }
- return 0;
- }
- static void ksz_phylink_get_caps(struct dsa_switch *ds, int port,
- struct phylink_config *config)
- {
- struct ksz_device *dev = ds->priv;
- config->legacy_pre_march2020 = false;
- if (dev->info->supports_mii[port])
- __set_bit(PHY_INTERFACE_MODE_MII, config->supported_interfaces);
- if (dev->info->supports_rmii[port])
- __set_bit(PHY_INTERFACE_MODE_RMII,
- config->supported_interfaces);
- if (dev->info->supports_rgmii[port])
- phy_interface_set_rgmii(config->supported_interfaces);
- if (dev->info->internal_phy[port]) {
- __set_bit(PHY_INTERFACE_MODE_INTERNAL,
- config->supported_interfaces);
- /* Compatibility for phylib's default interface type when the
- * phy-mode property is absent
- */
- __set_bit(PHY_INTERFACE_MODE_GMII,
- config->supported_interfaces);
- }
- if (dev->dev_ops->get_caps)
- dev->dev_ops->get_caps(dev, port, config);
- }
- void ksz_r_mib_stats64(struct ksz_device *dev, int port)
- {
- struct ethtool_pause_stats *pstats;
- struct rtnl_link_stats64 *stats;
- struct ksz_stats_raw *raw;
- struct ksz_port_mib *mib;
- mib = &dev->ports[port].mib;
- stats = &mib->stats64;
- pstats = &mib->pause_stats;
- raw = (struct ksz_stats_raw *)mib->counters;
- spin_lock(&mib->stats64_lock);
- stats->rx_packets = raw->rx_bcast + raw->rx_mcast + raw->rx_ucast +
- raw->rx_pause;
- stats->tx_packets = raw->tx_bcast + raw->tx_mcast + raw->tx_ucast +
- raw->tx_pause;
- /* HW counters are counting bytes + FCS which is not acceptable
- * for rtnl_link_stats64 interface
- */
- stats->rx_bytes = raw->rx_total - stats->rx_packets * ETH_FCS_LEN;
- stats->tx_bytes = raw->tx_total - stats->tx_packets * ETH_FCS_LEN;
- stats->rx_length_errors = raw->rx_undersize + raw->rx_fragments +
- raw->rx_oversize;
- stats->rx_crc_errors = raw->rx_crc_err;
- stats->rx_frame_errors = raw->rx_align_err;
- stats->rx_dropped = raw->rx_discards;
- stats->rx_errors = stats->rx_length_errors + stats->rx_crc_errors +
- stats->rx_frame_errors + stats->rx_dropped;
- stats->tx_window_errors = raw->tx_late_col;
- stats->tx_fifo_errors = raw->tx_discards;
- stats->tx_aborted_errors = raw->tx_exc_col;
- stats->tx_errors = stats->tx_window_errors + stats->tx_fifo_errors +
- stats->tx_aborted_errors;
- stats->multicast = raw->rx_mcast;
- stats->collisions = raw->tx_total_col;
- pstats->tx_pause_frames = raw->tx_pause;
- pstats->rx_pause_frames = raw->rx_pause;
- spin_unlock(&mib->stats64_lock);
- }
- static void ksz_get_stats64(struct dsa_switch *ds, int port,
- struct rtnl_link_stats64 *s)
- {
- struct ksz_device *dev = ds->priv;
- struct ksz_port_mib *mib;
- mib = &dev->ports[port].mib;
- spin_lock(&mib->stats64_lock);
- memcpy(s, &mib->stats64, sizeof(*s));
- spin_unlock(&mib->stats64_lock);
- }
- static void ksz_get_pause_stats(struct dsa_switch *ds, int port,
- struct ethtool_pause_stats *pause_stats)
- {
- struct ksz_device *dev = ds->priv;
- struct ksz_port_mib *mib;
- mib = &dev->ports[port].mib;
- spin_lock(&mib->stats64_lock);
- memcpy(pause_stats, &mib->pause_stats, sizeof(*pause_stats));
- spin_unlock(&mib->stats64_lock);
- }
- static void ksz_get_strings(struct dsa_switch *ds, int port,
- u32 stringset, uint8_t *buf)
- {
- struct ksz_device *dev = ds->priv;
- int i;
- if (stringset != ETH_SS_STATS)
- return;
- for (i = 0; i < dev->info->mib_cnt; i++) {
- memcpy(buf + i * ETH_GSTRING_LEN,
- dev->info->mib_names[i].string, ETH_GSTRING_LEN);
- }
- }
- static void ksz_update_port_member(struct ksz_device *dev, int port)
- {
- struct ksz_port *p = &dev->ports[port];
- struct dsa_switch *ds = dev->ds;
- u8 port_member = 0, cpu_port;
- const struct dsa_port *dp;
- int i, j;
- if (!dsa_is_user_port(ds, port))
- return;
- dp = dsa_to_port(ds, port);
- cpu_port = BIT(dsa_upstream_port(ds, port));
- for (i = 0; i < ds->num_ports; i++) {
- const struct dsa_port *other_dp = dsa_to_port(ds, i);
- struct ksz_port *other_p = &dev->ports[i];
- u8 val = 0;
- if (!dsa_is_user_port(ds, i))
- continue;
- if (port == i)
- continue;
- if (!dsa_port_bridge_same(dp, other_dp))
- continue;
- if (other_p->stp_state != BR_STATE_FORWARDING)
- continue;
- if (p->stp_state == BR_STATE_FORWARDING) {
- val |= BIT(port);
- port_member |= BIT(i);
- }
- /* Retain port [i]'s relationship to other ports than [port] */
- for (j = 0; j < ds->num_ports; j++) {
- const struct dsa_port *third_dp;
- struct ksz_port *third_p;
- if (j == i)
- continue;
- if (j == port)
- continue;
- if (!dsa_is_user_port(ds, j))
- continue;
- third_p = &dev->ports[j];
- if (third_p->stp_state != BR_STATE_FORWARDING)
- continue;
- third_dp = dsa_to_port(ds, j);
- if (dsa_port_bridge_same(other_dp, third_dp))
- val |= BIT(j);
- }
- dev->dev_ops->cfg_port_member(dev, i, val | cpu_port);
- }
- dev->dev_ops->cfg_port_member(dev, port, port_member | cpu_port);
- }
- static int ksz_sw_mdio_read(struct mii_bus *bus, int addr, int regnum)
- {
- struct ksz_device *dev = bus->priv;
- u16 val;
- int ret;
- if (regnum & MII_ADDR_C45)
- return -EOPNOTSUPP;
- ret = dev->dev_ops->r_phy(dev, addr, regnum, &val);
- if (ret < 0)
- return ret;
- return val;
- }
- static int ksz_sw_mdio_write(struct mii_bus *bus, int addr, int regnum,
- u16 val)
- {
- struct ksz_device *dev = bus->priv;
- if (regnum & MII_ADDR_C45)
- return -EOPNOTSUPP;
- return dev->dev_ops->w_phy(dev, addr, regnum, val);
- }
- static int ksz_irq_phy_setup(struct ksz_device *dev)
- {
- struct dsa_switch *ds = dev->ds;
- int phy;
- int irq;
- int ret;
- for (phy = 0; phy < KSZ_MAX_NUM_PORTS; phy++) {
- if (BIT(phy) & ds->phys_mii_mask) {
- irq = irq_find_mapping(dev->ports[phy].pirq.domain,
- PORT_SRC_PHY_INT);
- if (irq < 0) {
- ret = irq;
- goto out;
- }
- ds->slave_mii_bus->irq[phy] = irq;
- }
- }
- return 0;
- out:
- while (phy--)
- if (BIT(phy) & ds->phys_mii_mask)
- irq_dispose_mapping(ds->slave_mii_bus->irq[phy]);
- return ret;
- }
- static void ksz_irq_phy_free(struct ksz_device *dev)
- {
- struct dsa_switch *ds = dev->ds;
- int phy;
- for (phy = 0; phy < KSZ_MAX_NUM_PORTS; phy++)
- if (BIT(phy) & ds->phys_mii_mask)
- irq_dispose_mapping(ds->slave_mii_bus->irq[phy]);
- }
- static int ksz_mdio_register(struct ksz_device *dev)
- {
- struct dsa_switch *ds = dev->ds;
- struct device_node *mdio_np;
- struct mii_bus *bus;
- int ret;
- mdio_np = of_get_child_by_name(dev->dev->of_node, "mdio");
- if (!mdio_np)
- return 0;
- bus = devm_mdiobus_alloc(ds->dev);
- if (!bus) {
- of_node_put(mdio_np);
- return -ENOMEM;
- }
- bus->priv = dev;
- bus->read = ksz_sw_mdio_read;
- bus->write = ksz_sw_mdio_write;
- bus->name = "ksz slave smi";
- snprintf(bus->id, MII_BUS_ID_SIZE, "SMI-%d", ds->index);
- bus->parent = ds->dev;
- bus->phy_mask = ~ds->phys_mii_mask;
- ds->slave_mii_bus = bus;
- if (dev->irq > 0) {
- ret = ksz_irq_phy_setup(dev);
- if (ret) {
- of_node_put(mdio_np);
- return ret;
- }
- }
- ret = devm_of_mdiobus_register(ds->dev, bus, mdio_np);
- if (ret) {
- dev_err(ds->dev, "unable to register MDIO bus %s\n",
- bus->id);
- if (dev->irq > 0)
- ksz_irq_phy_free(dev);
- }
- of_node_put(mdio_np);
- return ret;
- }
- static void ksz_irq_mask(struct irq_data *d)
- {
- struct ksz_irq *kirq = irq_data_get_irq_chip_data(d);
- kirq->masked |= BIT(d->hwirq);
- }
- static void ksz_irq_unmask(struct irq_data *d)
- {
- struct ksz_irq *kirq = irq_data_get_irq_chip_data(d);
- kirq->masked &= ~BIT(d->hwirq);
- }
- static void ksz_irq_bus_lock(struct irq_data *d)
- {
- struct ksz_irq *kirq = irq_data_get_irq_chip_data(d);
- mutex_lock(&kirq->dev->lock_irq);
- }
- static void ksz_irq_bus_sync_unlock(struct irq_data *d)
- {
- struct ksz_irq *kirq = irq_data_get_irq_chip_data(d);
- struct ksz_device *dev = kirq->dev;
- int ret;
- ret = ksz_write32(dev, kirq->reg_mask, kirq->masked);
- if (ret)
- dev_err(dev->dev, "failed to change IRQ mask\n");
- mutex_unlock(&dev->lock_irq);
- }
- static const struct irq_chip ksz_irq_chip = {
- .name = "ksz-irq",
- .irq_mask = ksz_irq_mask,
- .irq_unmask = ksz_irq_unmask,
- .irq_bus_lock = ksz_irq_bus_lock,
- .irq_bus_sync_unlock = ksz_irq_bus_sync_unlock,
- };
- static int ksz_irq_domain_map(struct irq_domain *d,
- unsigned int irq, irq_hw_number_t hwirq)
- {
- irq_set_chip_data(irq, d->host_data);
- irq_set_chip_and_handler(irq, &ksz_irq_chip, handle_level_irq);
- irq_set_noprobe(irq);
- return 0;
- }
- static const struct irq_domain_ops ksz_irq_domain_ops = {
- .map = ksz_irq_domain_map,
- .xlate = irq_domain_xlate_twocell,
- };
- static void ksz_irq_free(struct ksz_irq *kirq)
- {
- int irq, virq;
- free_irq(kirq->irq_num, kirq);
- for (irq = 0; irq < kirq->nirqs; irq++) {
- virq = irq_find_mapping(kirq->domain, irq);
- irq_dispose_mapping(virq);
- }
- irq_domain_remove(kirq->domain);
- }
- static irqreturn_t ksz_irq_thread_fn(int irq, void *dev_id)
- {
- struct ksz_irq *kirq = dev_id;
- unsigned int nhandled = 0;
- struct ksz_device *dev;
- unsigned int sub_irq;
- u8 data;
- int ret;
- u8 n;
- dev = kirq->dev;
- /* Read interrupt status register */
- ret = ksz_read8(dev, kirq->reg_status, &data);
- if (ret)
- goto out;
- for (n = 0; n < kirq->nirqs; ++n) {
- if (data & BIT(n)) {
- sub_irq = irq_find_mapping(kirq->domain, n);
- handle_nested_irq(sub_irq);
- ++nhandled;
- }
- }
- out:
- return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
- }
- static int ksz_irq_common_setup(struct ksz_device *dev, struct ksz_irq *kirq)
- {
- int ret, n;
- kirq->dev = dev;
- kirq->masked = ~0;
- kirq->domain = irq_domain_add_simple(dev->dev->of_node, kirq->nirqs, 0,
- &ksz_irq_domain_ops, kirq);
- if (!kirq->domain)
- return -ENOMEM;
- for (n = 0; n < kirq->nirqs; n++)
- irq_create_mapping(kirq->domain, n);
- ret = request_threaded_irq(kirq->irq_num, NULL, ksz_irq_thread_fn,
- IRQF_ONESHOT, kirq->name, kirq);
- if (ret)
- goto out;
- return 0;
- out:
- ksz_irq_free(kirq);
- return ret;
- }
- static int ksz_girq_setup(struct ksz_device *dev)
- {
- struct ksz_irq *girq = &dev->girq;
- girq->nirqs = dev->info->port_cnt;
- girq->reg_mask = REG_SW_PORT_INT_MASK__1;
- girq->reg_status = REG_SW_PORT_INT_STATUS__1;
- snprintf(girq->name, sizeof(girq->name), "global_port_irq");
- girq->irq_num = dev->irq;
- return ksz_irq_common_setup(dev, girq);
- }
- static int ksz_pirq_setup(struct ksz_device *dev, u8 p)
- {
- struct ksz_irq *pirq = &dev->ports[p].pirq;
- pirq->nirqs = dev->info->port_nirqs;
- pirq->reg_mask = dev->dev_ops->get_port_addr(p, REG_PORT_INT_MASK);
- pirq->reg_status = dev->dev_ops->get_port_addr(p, REG_PORT_INT_STATUS);
- snprintf(pirq->name, sizeof(pirq->name), "port_irq-%d", p);
- pirq->irq_num = irq_find_mapping(dev->girq.domain, p);
- if (pirq->irq_num < 0)
- return pirq->irq_num;
- return ksz_irq_common_setup(dev, pirq);
- }
- static int ksz_setup(struct dsa_switch *ds)
- {
- struct ksz_device *dev = ds->priv;
- struct dsa_port *dp;
- struct ksz_port *p;
- const u16 *regs;
- int ret;
- regs = dev->info->regs;
- dev->vlan_cache = devm_kcalloc(dev->dev, sizeof(struct vlan_table),
- dev->info->num_vlans, GFP_KERNEL);
- if (!dev->vlan_cache)
- return -ENOMEM;
- ret = dev->dev_ops->reset(dev);
- if (ret) {
- dev_err(ds->dev, "failed to reset switch\n");
- return ret;
- }
- /* set broadcast storm protection 10% rate */
- regmap_update_bits(dev->regmap[1], regs[S_BROADCAST_CTRL],
- BROADCAST_STORM_RATE,
- (BROADCAST_STORM_VALUE *
- BROADCAST_STORM_PROT_RATE) / 100);
- dev->dev_ops->config_cpu_port(ds);
- dev->dev_ops->enable_stp_addr(dev);
- regmap_update_bits(dev->regmap[0], regs[S_MULTICAST_CTRL],
- MULTICAST_STORM_DISABLE, MULTICAST_STORM_DISABLE);
- ksz_init_mib_timer(dev);
- ds->configure_vlan_while_not_filtering = false;
- if (dev->dev_ops->setup) {
- ret = dev->dev_ops->setup(ds);
- if (ret)
- return ret;
- }
- /* Start with learning disabled on standalone user ports, and enabled
- * on the CPU port. In lack of other finer mechanisms, learning on the
- * CPU port will avoid flooding bridge local addresses on the network
- * in some cases.
- */
- p = &dev->ports[dev->cpu_port];
- p->learning = true;
- if (dev->irq > 0) {
- ret = ksz_girq_setup(dev);
- if (ret)
- return ret;
- dsa_switch_for_each_user_port(dp, dev->ds) {
- ret = ksz_pirq_setup(dev, dp->index);
- if (ret)
- goto out_girq;
- }
- }
- ret = ksz_mdio_register(dev);
- if (ret < 0) {
- dev_err(dev->dev, "failed to register the mdio");
- goto out_pirq;
- }
- /* start switch */
- regmap_update_bits(dev->regmap[0], regs[S_START_CTRL],
- SW_START, SW_START);
- return 0;
- out_pirq:
- if (dev->irq > 0)
- dsa_switch_for_each_user_port(dp, dev->ds)
- ksz_irq_free(&dev->ports[dp->index].pirq);
- out_girq:
- if (dev->irq > 0)
- ksz_irq_free(&dev->girq);
- return ret;
- }
- static void ksz_teardown(struct dsa_switch *ds)
- {
- struct ksz_device *dev = ds->priv;
- struct dsa_port *dp;
- if (dev->irq > 0) {
- dsa_switch_for_each_user_port(dp, dev->ds)
- ksz_irq_free(&dev->ports[dp->index].pirq);
- ksz_irq_free(&dev->girq);
- }
- if (dev->dev_ops->teardown)
- dev->dev_ops->teardown(ds);
- }
- static void port_r_cnt(struct ksz_device *dev, int port)
- {
- struct ksz_port_mib *mib = &dev->ports[port].mib;
- u64 *dropped;
- /* Some ports may not have MIB counters before SWITCH_COUNTER_NUM. */
- while (mib->cnt_ptr < dev->info->reg_mib_cnt) {
- dev->dev_ops->r_mib_cnt(dev, port, mib->cnt_ptr,
- &mib->counters[mib->cnt_ptr]);
- ++mib->cnt_ptr;
- }
- /* last one in storage */
- dropped = &mib->counters[dev->info->mib_cnt];
- /* Some ports may not have MIB counters after SWITCH_COUNTER_NUM. */
- while (mib->cnt_ptr < dev->info->mib_cnt) {
- dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr,
- dropped, &mib->counters[mib->cnt_ptr]);
- ++mib->cnt_ptr;
- }
- mib->cnt_ptr = 0;
- }
- static void ksz_mib_read_work(struct work_struct *work)
- {
- struct ksz_device *dev = container_of(work, struct ksz_device,
- mib_read.work);
- struct ksz_port_mib *mib;
- struct ksz_port *p;
- int i;
- for (i = 0; i < dev->info->port_cnt; i++) {
- if (dsa_is_unused_port(dev->ds, i))
- continue;
- p = &dev->ports[i];
- mib = &p->mib;
- mutex_lock(&mib->cnt_mutex);
- /* Only read MIB counters when the port is told to do.
- * If not, read only dropped counters when link is not up.
- */
- if (!p->read) {
- const struct dsa_port *dp = dsa_to_port(dev->ds, i);
- if (!netif_carrier_ok(dp->slave))
- mib->cnt_ptr = dev->info->reg_mib_cnt;
- }
- port_r_cnt(dev, i);
- p->read = false;
- if (dev->dev_ops->r_mib_stat64)
- dev->dev_ops->r_mib_stat64(dev, i);
- mutex_unlock(&mib->cnt_mutex);
- }
- schedule_delayed_work(&dev->mib_read, dev->mib_read_interval);
- }
- void ksz_init_mib_timer(struct ksz_device *dev)
- {
- int i;
- INIT_DELAYED_WORK(&dev->mib_read, ksz_mib_read_work);
- for (i = 0; i < dev->info->port_cnt; i++) {
- struct ksz_port_mib *mib = &dev->ports[i].mib;
- dev->dev_ops->port_init_cnt(dev, i);
- mib->cnt_ptr = 0;
- memset(mib->counters, 0, dev->info->mib_cnt * sizeof(u64));
- }
- }
- static int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg)
- {
- struct ksz_device *dev = ds->priv;
- u16 val = 0xffff;
- int ret;
- ret = dev->dev_ops->r_phy(dev, addr, reg, &val);
- if (ret)
- return ret;
- return val;
- }
- static int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val)
- {
- struct ksz_device *dev = ds->priv;
- int ret;
- ret = dev->dev_ops->w_phy(dev, addr, reg, val);
- if (ret)
- return ret;
- return 0;
- }
- static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port)
- {
- struct ksz_device *dev = ds->priv;
- if (dev->chip_id == KSZ8830_CHIP_ID) {
- /* Silicon Errata Sheet (DS80000830A):
- * Port 1 does not work with LinkMD Cable-Testing.
- * Port 1 does not respond to received PAUSE control frames.
- */
- if (!port)
- return MICREL_KSZ8_P1_ERRATA;
- }
- return 0;
- }
- static void ksz_mac_link_down(struct dsa_switch *ds, int port,
- unsigned int mode, phy_interface_t interface)
- {
- struct ksz_device *dev = ds->priv;
- struct ksz_port *p = &dev->ports[port];
- /* Read all MIB counters when the link is going down. */
- p->read = true;
- /* timer started */
- if (dev->mib_read_interval)
- schedule_delayed_work(&dev->mib_read, 0);
- }
- static int ksz_sset_count(struct dsa_switch *ds, int port, int sset)
- {
- struct ksz_device *dev = ds->priv;
- if (sset != ETH_SS_STATS)
- return 0;
- return dev->info->mib_cnt;
- }
- static void ksz_get_ethtool_stats(struct dsa_switch *ds, int port,
- uint64_t *buf)
- {
- const struct dsa_port *dp = dsa_to_port(ds, port);
- struct ksz_device *dev = ds->priv;
- struct ksz_port_mib *mib;
- mib = &dev->ports[port].mib;
- mutex_lock(&mib->cnt_mutex);
- /* Only read dropped counters if no link. */
- if (!netif_carrier_ok(dp->slave))
- mib->cnt_ptr = dev->info->reg_mib_cnt;
- port_r_cnt(dev, port);
- memcpy(buf, mib->counters, dev->info->mib_cnt * sizeof(u64));
- mutex_unlock(&mib->cnt_mutex);
- }
- static int ksz_port_bridge_join(struct dsa_switch *ds, int port,
- struct dsa_bridge bridge,
- bool *tx_fwd_offload,
- struct netlink_ext_ack *extack)
- {
- /* port_stp_state_set() will be called after to put the port in
- * appropriate state so there is no need to do anything.
- */
- return 0;
- }
- static void ksz_port_bridge_leave(struct dsa_switch *ds, int port,
- struct dsa_bridge bridge)
- {
- /* port_stp_state_set() will be called after to put the port in
- * forwarding state so there is no need to do anything.
- */
- }
- static void ksz_port_fast_age(struct dsa_switch *ds, int port)
- {
- struct ksz_device *dev = ds->priv;
- dev->dev_ops->flush_dyn_mac_table(dev, port);
- }
- static int ksz_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)
- {
- struct ksz_device *dev = ds->priv;
- if (!dev->dev_ops->set_ageing_time)
- return -EOPNOTSUPP;
- return dev->dev_ops->set_ageing_time(dev, msecs);
- }
- static int ksz_port_fdb_add(struct dsa_switch *ds, int port,
- const unsigned char *addr, u16 vid,
- struct dsa_db db)
- {
- struct ksz_device *dev = ds->priv;
- if (!dev->dev_ops->fdb_add)
- return -EOPNOTSUPP;
- return dev->dev_ops->fdb_add(dev, port, addr, vid, db);
- }
- static int ksz_port_fdb_del(struct dsa_switch *ds, int port,
- const unsigned char *addr,
- u16 vid, struct dsa_db db)
- {
- struct ksz_device *dev = ds->priv;
- if (!dev->dev_ops->fdb_del)
- return -EOPNOTSUPP;
- return dev->dev_ops->fdb_del(dev, port, addr, vid, db);
- }
- static int ksz_port_fdb_dump(struct dsa_switch *ds, int port,
- dsa_fdb_dump_cb_t *cb, void *data)
- {
- struct ksz_device *dev = ds->priv;
- if (!dev->dev_ops->fdb_dump)
- return -EOPNOTSUPP;
- return dev->dev_ops->fdb_dump(dev, port, cb, data);
- }
- static int ksz_port_mdb_add(struct dsa_switch *ds, int port,
- const struct switchdev_obj_port_mdb *mdb,
- struct dsa_db db)
- {
- struct ksz_device *dev = ds->priv;
- if (!dev->dev_ops->mdb_add)
- return -EOPNOTSUPP;
- return dev->dev_ops->mdb_add(dev, port, mdb, db);
- }
- static int ksz_port_mdb_del(struct dsa_switch *ds, int port,
- const struct switchdev_obj_port_mdb *mdb,
- struct dsa_db db)
- {
- struct ksz_device *dev = ds->priv;
- if (!dev->dev_ops->mdb_del)
- return -EOPNOTSUPP;
- return dev->dev_ops->mdb_del(dev, port, mdb, db);
- }
- static int ksz_enable_port(struct dsa_switch *ds, int port,
- struct phy_device *phy)
- {
- struct ksz_device *dev = ds->priv;
- if (!dsa_is_user_port(ds, port))
- return 0;
- /* setup slave port */
- dev->dev_ops->port_setup(dev, port, false);
- /* port_stp_state_set() will be called after to enable the port so
- * there is no need to do anything.
- */
- return 0;
- }
- void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
- {
- struct ksz_device *dev = ds->priv;
- struct ksz_port *p;
- const u16 *regs;
- u8 data;
- regs = dev->info->regs;
- ksz_pread8(dev, port, regs[P_STP_CTRL], &data);
- data &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE);
- p = &dev->ports[port];
- switch (state) {
- case BR_STATE_DISABLED:
- data |= PORT_LEARN_DISABLE;
- break;
- case BR_STATE_LISTENING:
- data |= (PORT_RX_ENABLE | PORT_LEARN_DISABLE);
- break;
- case BR_STATE_LEARNING:
- data |= PORT_RX_ENABLE;
- if (!p->learning)
- data |= PORT_LEARN_DISABLE;
- break;
- case BR_STATE_FORWARDING:
- data |= (PORT_TX_ENABLE | PORT_RX_ENABLE);
- if (!p->learning)
- data |= PORT_LEARN_DISABLE;
- break;
- case BR_STATE_BLOCKING:
- data |= PORT_LEARN_DISABLE;
- break;
- default:
- dev_err(ds->dev, "invalid STP state: %d\n", state);
- return;
- }
- ksz_pwrite8(dev, port, regs[P_STP_CTRL], data);
- p->stp_state = state;
- ksz_update_port_member(dev, port);
- }
- static int ksz_port_pre_bridge_flags(struct dsa_switch *ds, int port,
- struct switchdev_brport_flags flags,
- struct netlink_ext_ack *extack)
- {
- if (flags.mask & ~BR_LEARNING)
- return -EINVAL;
- return 0;
- }
- static int ksz_port_bridge_flags(struct dsa_switch *ds, int port,
- struct switchdev_brport_flags flags,
- struct netlink_ext_ack *extack)
- {
- struct ksz_device *dev = ds->priv;
- struct ksz_port *p = &dev->ports[port];
- if (flags.mask & BR_LEARNING) {
- p->learning = !!(flags.val & BR_LEARNING);
- /* Make the change take effect immediately */
- ksz_port_stp_state_set(ds, port, p->stp_state);
- }
- return 0;
- }
- static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds,
- int port,
- enum dsa_tag_protocol mp)
- {
- struct ksz_device *dev = ds->priv;
- enum dsa_tag_protocol proto = DSA_TAG_PROTO_NONE;
- if (dev->chip_id == KSZ8795_CHIP_ID ||
- dev->chip_id == KSZ8794_CHIP_ID ||
- dev->chip_id == KSZ8765_CHIP_ID)
- proto = DSA_TAG_PROTO_KSZ8795;
- if (dev->chip_id == KSZ8830_CHIP_ID ||
- dev->chip_id == KSZ8563_CHIP_ID ||
- dev->chip_id == KSZ9893_CHIP_ID)
- proto = DSA_TAG_PROTO_KSZ9893;
- if (dev->chip_id == KSZ9477_CHIP_ID ||
- dev->chip_id == KSZ9896_CHIP_ID ||
- dev->chip_id == KSZ9897_CHIP_ID ||
- dev->chip_id == KSZ9567_CHIP_ID)
- proto = DSA_TAG_PROTO_KSZ9477;
- if (is_lan937x(dev))
- proto = DSA_TAG_PROTO_LAN937X_VALUE;
- return proto;
- }
- static int ksz_port_vlan_filtering(struct dsa_switch *ds, int port,
- bool flag, struct netlink_ext_ack *extack)
- {
- struct ksz_device *dev = ds->priv;
- if (!dev->dev_ops->vlan_filtering)
- return -EOPNOTSUPP;
- return dev->dev_ops->vlan_filtering(dev, port, flag, extack);
- }
- static int ksz_port_vlan_add(struct dsa_switch *ds, int port,
- const struct switchdev_obj_port_vlan *vlan,
- struct netlink_ext_ack *extack)
- {
- struct ksz_device *dev = ds->priv;
- if (!dev->dev_ops->vlan_add)
- return -EOPNOTSUPP;
- return dev->dev_ops->vlan_add(dev, port, vlan, extack);
- }
- static int ksz_port_vlan_del(struct dsa_switch *ds, int port,
- const struct switchdev_obj_port_vlan *vlan)
- {
- struct ksz_device *dev = ds->priv;
- if (!dev->dev_ops->vlan_del)
- return -EOPNOTSUPP;
- return dev->dev_ops->vlan_del(dev, port, vlan);
- }
- static int ksz_port_mirror_add(struct dsa_switch *ds, int port,
- struct dsa_mall_mirror_tc_entry *mirror,
- bool ingress, struct netlink_ext_ack *extack)
- {
- struct ksz_device *dev = ds->priv;
- if (!dev->dev_ops->mirror_add)
- return -EOPNOTSUPP;
- return dev->dev_ops->mirror_add(dev, port, mirror, ingress, extack);
- }
- static void ksz_port_mirror_del(struct dsa_switch *ds, int port,
- struct dsa_mall_mirror_tc_entry *mirror)
- {
- struct ksz_device *dev = ds->priv;
- if (dev->dev_ops->mirror_del)
- dev->dev_ops->mirror_del(dev, port, mirror);
- }
- static int ksz_change_mtu(struct dsa_switch *ds, int port, int mtu)
- {
- struct ksz_device *dev = ds->priv;
- if (!dev->dev_ops->change_mtu)
- return -EOPNOTSUPP;
- return dev->dev_ops->change_mtu(dev, port, mtu);
- }
- static int ksz_max_mtu(struct dsa_switch *ds, int port)
- {
- struct ksz_device *dev = ds->priv;
- if (!dev->dev_ops->max_mtu)
- return -EOPNOTSUPP;
- return dev->dev_ops->max_mtu(dev, port);
- }
- static void ksz_set_xmii(struct ksz_device *dev, int port,
- phy_interface_t interface)
- {
- const u8 *bitval = dev->info->xmii_ctrl1;
- struct ksz_port *p = &dev->ports[port];
- const u16 *regs = dev->info->regs;
- u8 data8;
- ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8);
- data8 &= ~(P_MII_SEL_M | P_RGMII_ID_IG_ENABLE |
- P_RGMII_ID_EG_ENABLE);
- switch (interface) {
- case PHY_INTERFACE_MODE_MII:
- data8 |= bitval[P_MII_SEL];
- break;
- case PHY_INTERFACE_MODE_RMII:
- data8 |= bitval[P_RMII_SEL];
- break;
- case PHY_INTERFACE_MODE_GMII:
- data8 |= bitval[P_GMII_SEL];
- break;
- case PHY_INTERFACE_MODE_RGMII:
- case PHY_INTERFACE_MODE_RGMII_ID:
- case PHY_INTERFACE_MODE_RGMII_TXID:
- case PHY_INTERFACE_MODE_RGMII_RXID:
- data8 |= bitval[P_RGMII_SEL];
- /* On KSZ9893, disable RGMII in-band status support */
- if (dev->chip_id == KSZ9893_CHIP_ID ||
- dev->chip_id == KSZ8563_CHIP_ID)
- data8 &= ~P_MII_MAC_MODE;
- break;
- default:
- dev_err(dev->dev, "Unsupported interface '%s' for port %d\n",
- phy_modes(interface), port);
- return;
- }
- if (p->rgmii_tx_val)
- data8 |= P_RGMII_ID_EG_ENABLE;
- if (p->rgmii_rx_val)
- data8 |= P_RGMII_ID_IG_ENABLE;
- /* Write the updated value */
- ksz_pwrite8(dev, port, regs[P_XMII_CTRL_1], data8);
- }
- phy_interface_t ksz_get_xmii(struct ksz_device *dev, int port, bool gbit)
- {
- const u8 *bitval = dev->info->xmii_ctrl1;
- const u16 *regs = dev->info->regs;
- phy_interface_t interface;
- u8 data8;
- u8 val;
- ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8);
- val = FIELD_GET(P_MII_SEL_M, data8);
- if (val == bitval[P_MII_SEL]) {
- if (gbit)
- interface = PHY_INTERFACE_MODE_GMII;
- else
- interface = PHY_INTERFACE_MODE_MII;
- } else if (val == bitval[P_RMII_SEL]) {
- interface = PHY_INTERFACE_MODE_RGMII;
- } else {
- interface = PHY_INTERFACE_MODE_RGMII;
- if (data8 & P_RGMII_ID_EG_ENABLE)
- interface = PHY_INTERFACE_MODE_RGMII_TXID;
- if (data8 & P_RGMII_ID_IG_ENABLE) {
- interface = PHY_INTERFACE_MODE_RGMII_RXID;
- if (data8 & P_RGMII_ID_EG_ENABLE)
- interface = PHY_INTERFACE_MODE_RGMII_ID;
- }
- }
- return interface;
- }
- static void ksz_phylink_mac_config(struct dsa_switch *ds, int port,
- unsigned int mode,
- const struct phylink_link_state *state)
- {
- struct ksz_device *dev = ds->priv;
- if (ksz_is_ksz88x3(dev))
- return;
- /* Internal PHYs */
- if (dev->info->internal_phy[port])
- return;
- if (phylink_autoneg_inband(mode)) {
- dev_err(dev->dev, "In-band AN not supported!\n");
- return;
- }
- ksz_set_xmii(dev, port, state->interface);
- if (dev->dev_ops->phylink_mac_config)
- dev->dev_ops->phylink_mac_config(dev, port, mode, state);
- if (dev->dev_ops->setup_rgmii_delay)
- dev->dev_ops->setup_rgmii_delay(dev, port);
- }
- bool ksz_get_gbit(struct ksz_device *dev, int port)
- {
- const u8 *bitval = dev->info->xmii_ctrl1;
- const u16 *regs = dev->info->regs;
- bool gbit = false;
- u8 data8;
- bool val;
- ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8);
- val = FIELD_GET(P_GMII_1GBIT_M, data8);
- if (val == bitval[P_GMII_1GBIT])
- gbit = true;
- return gbit;
- }
- static void ksz_set_gbit(struct ksz_device *dev, int port, bool gbit)
- {
- const u8 *bitval = dev->info->xmii_ctrl1;
- const u16 *regs = dev->info->regs;
- u8 data8;
- ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8);
- data8 &= ~P_GMII_1GBIT_M;
- if (gbit)
- data8 |= FIELD_PREP(P_GMII_1GBIT_M, bitval[P_GMII_1GBIT]);
- else
- data8 |= FIELD_PREP(P_GMII_1GBIT_M, bitval[P_GMII_NOT_1GBIT]);
- /* Write the updated value */
- ksz_pwrite8(dev, port, regs[P_XMII_CTRL_1], data8);
- }
- static void ksz_set_100_10mbit(struct ksz_device *dev, int port, int speed)
- {
- const u8 *bitval = dev->info->xmii_ctrl0;
- const u16 *regs = dev->info->regs;
- u8 data8;
- ksz_pread8(dev, port, regs[P_XMII_CTRL_0], &data8);
- data8 &= ~P_MII_100MBIT_M;
- if (speed == SPEED_100)
- data8 |= FIELD_PREP(P_MII_100MBIT_M, bitval[P_MII_100MBIT]);
- else
- data8 |= FIELD_PREP(P_MII_100MBIT_M, bitval[P_MII_10MBIT]);
- /* Write the updated value */
- ksz_pwrite8(dev, port, regs[P_XMII_CTRL_0], data8);
- }
- static void ksz_port_set_xmii_speed(struct ksz_device *dev, int port, int speed)
- {
- if (speed == SPEED_1000)
- ksz_set_gbit(dev, port, true);
- else
- ksz_set_gbit(dev, port, false);
- if (speed == SPEED_100 || speed == SPEED_10)
- ksz_set_100_10mbit(dev, port, speed);
- }
- static void ksz_duplex_flowctrl(struct ksz_device *dev, int port, int duplex,
- bool tx_pause, bool rx_pause)
- {
- const u8 *bitval = dev->info->xmii_ctrl0;
- const u32 *masks = dev->info->masks;
- const u16 *regs = dev->info->regs;
- u8 mask;
- u8 val;
- mask = P_MII_DUPLEX_M | masks[P_MII_TX_FLOW_CTRL] |
- masks[P_MII_RX_FLOW_CTRL];
- if (duplex == DUPLEX_FULL)
- val = FIELD_PREP(P_MII_DUPLEX_M, bitval[P_MII_FULL_DUPLEX]);
- else
- val = FIELD_PREP(P_MII_DUPLEX_M, bitval[P_MII_HALF_DUPLEX]);
- if (tx_pause)
- val |= masks[P_MII_TX_FLOW_CTRL];
- if (rx_pause)
- val |= masks[P_MII_RX_FLOW_CTRL];
- ksz_prmw8(dev, port, regs[P_XMII_CTRL_0], mask, val);
- }
- static void ksz9477_phylink_mac_link_up(struct ksz_device *dev, int port,
- unsigned int mode,
- phy_interface_t interface,
- struct phy_device *phydev, int speed,
- int duplex, bool tx_pause,
- bool rx_pause)
- {
- struct ksz_port *p;
- p = &dev->ports[port];
- /* Internal PHYs */
- if (dev->info->internal_phy[port])
- return;
- p->phydev.speed = speed;
- ksz_port_set_xmii_speed(dev, port, speed);
- ksz_duplex_flowctrl(dev, port, duplex, tx_pause, rx_pause);
- }
- static void ksz_phylink_mac_link_up(struct dsa_switch *ds, int port,
- unsigned int mode,
- phy_interface_t interface,
- struct phy_device *phydev, int speed,
- int duplex, bool tx_pause, bool rx_pause)
- {
- struct ksz_device *dev = ds->priv;
- if (dev->dev_ops->phylink_mac_link_up)
- dev->dev_ops->phylink_mac_link_up(dev, port, mode, interface,
- phydev, speed, duplex,
- tx_pause, rx_pause);
- }
- static int ksz_switch_detect(struct ksz_device *dev)
- {
- u8 id1, id2, id4;
- u16 id16;
- u32 id32;
- int ret;
- /* read chip id */
- ret = ksz_read16(dev, REG_CHIP_ID0, &id16);
- if (ret)
- return ret;
- id1 = FIELD_GET(SW_FAMILY_ID_M, id16);
- id2 = FIELD_GET(SW_CHIP_ID_M, id16);
- switch (id1) {
- case KSZ87_FAMILY_ID:
- if (id2 == KSZ87_CHIP_ID_95) {
- u8 val;
- dev->chip_id = KSZ8795_CHIP_ID;
- ksz_read8(dev, KSZ8_PORT_STATUS_0, &val);
- if (val & KSZ8_PORT_FIBER_MODE)
- dev->chip_id = KSZ8765_CHIP_ID;
- } else if (id2 == KSZ87_CHIP_ID_94) {
- dev->chip_id = KSZ8794_CHIP_ID;
- } else {
- return -ENODEV;
- }
- break;
- case KSZ88_FAMILY_ID:
- if (id2 == KSZ88_CHIP_ID_63)
- dev->chip_id = KSZ8830_CHIP_ID;
- else
- return -ENODEV;
- break;
- default:
- ret = ksz_read32(dev, REG_CHIP_ID0, &id32);
- if (ret)
- return ret;
- dev->chip_rev = FIELD_GET(SW_REV_ID_M, id32);
- id32 &= ~0xFF;
- switch (id32) {
- case KSZ9477_CHIP_ID:
- case KSZ9896_CHIP_ID:
- case KSZ9897_CHIP_ID:
- case KSZ9567_CHIP_ID:
- case LAN9370_CHIP_ID:
- case LAN9371_CHIP_ID:
- case LAN9372_CHIP_ID:
- case LAN9373_CHIP_ID:
- case LAN9374_CHIP_ID:
- dev->chip_id = id32;
- break;
- case KSZ9893_CHIP_ID:
- ret = ksz_read8(dev, REG_CHIP_ID4,
- &id4);
- if (ret)
- return ret;
- if (id4 == SKU_ID_KSZ8563)
- dev->chip_id = KSZ8563_CHIP_ID;
- else
- dev->chip_id = KSZ9893_CHIP_ID;
- break;
- default:
- dev_err(dev->dev,
- "unsupported switch detected %x)\n", id32);
- return -ENODEV;
- }
- }
- return 0;
- }
- static const struct dsa_switch_ops ksz_switch_ops = {
- .get_tag_protocol = ksz_get_tag_protocol,
- .get_phy_flags = ksz_get_phy_flags,
- .setup = ksz_setup,
- .teardown = ksz_teardown,
- .phy_read = ksz_phy_read16,
- .phy_write = ksz_phy_write16,
- .phylink_get_caps = ksz_phylink_get_caps,
- .phylink_mac_config = ksz_phylink_mac_config,
- .phylink_mac_link_up = ksz_phylink_mac_link_up,
- .phylink_mac_link_down = ksz_mac_link_down,
- .port_enable = ksz_enable_port,
- .set_ageing_time = ksz_set_ageing_time,
- .get_strings = ksz_get_strings,
- .get_ethtool_stats = ksz_get_ethtool_stats,
- .get_sset_count = ksz_sset_count,
- .port_bridge_join = ksz_port_bridge_join,
- .port_bridge_leave = ksz_port_bridge_leave,
- .port_stp_state_set = ksz_port_stp_state_set,
- .port_pre_bridge_flags = ksz_port_pre_bridge_flags,
- .port_bridge_flags = ksz_port_bridge_flags,
- .port_fast_age = ksz_port_fast_age,
- .port_vlan_filtering = ksz_port_vlan_filtering,
- .port_vlan_add = ksz_port_vlan_add,
- .port_vlan_del = ksz_port_vlan_del,
- .port_fdb_dump = ksz_port_fdb_dump,
- .port_fdb_add = ksz_port_fdb_add,
- .port_fdb_del = ksz_port_fdb_del,
- .port_mdb_add = ksz_port_mdb_add,
- .port_mdb_del = ksz_port_mdb_del,
- .port_mirror_add = ksz_port_mirror_add,
- .port_mirror_del = ksz_port_mirror_del,
- .get_stats64 = ksz_get_stats64,
- .get_pause_stats = ksz_get_pause_stats,
- .port_change_mtu = ksz_change_mtu,
- .port_max_mtu = ksz_max_mtu,
- };
- struct ksz_device *ksz_switch_alloc(struct device *base, void *priv)
- {
- struct dsa_switch *ds;
- struct ksz_device *swdev;
- ds = devm_kzalloc(base, sizeof(*ds), GFP_KERNEL);
- if (!ds)
- return NULL;
- ds->dev = base;
- ds->num_ports = DSA_MAX_PORTS;
- ds->ops = &ksz_switch_ops;
- swdev = devm_kzalloc(base, sizeof(*swdev), GFP_KERNEL);
- if (!swdev)
- return NULL;
- ds->priv = swdev;
- swdev->dev = base;
- swdev->ds = ds;
- swdev->priv = priv;
- return swdev;
- }
- EXPORT_SYMBOL(ksz_switch_alloc);
- static void ksz_parse_rgmii_delay(struct ksz_device *dev, int port_num,
- struct device_node *port_dn)
- {
- phy_interface_t phy_mode = dev->ports[port_num].interface;
- int rx_delay = -1, tx_delay = -1;
- if (!phy_interface_mode_is_rgmii(phy_mode))
- return;
- of_property_read_u32(port_dn, "rx-internal-delay-ps", &rx_delay);
- of_property_read_u32(port_dn, "tx-internal-delay-ps", &tx_delay);
- if (rx_delay == -1 && tx_delay == -1) {
- dev_warn(dev->dev,
- "Port %d interpreting RGMII delay settings based on \"phy-mode\" property, "
- "please update device tree to specify \"rx-internal-delay-ps\" and "
- "\"tx-internal-delay-ps\"",
- port_num);
- if (phy_mode == PHY_INTERFACE_MODE_RGMII_RXID ||
- phy_mode == PHY_INTERFACE_MODE_RGMII_ID)
- rx_delay = 2000;
- if (phy_mode == PHY_INTERFACE_MODE_RGMII_TXID ||
- phy_mode == PHY_INTERFACE_MODE_RGMII_ID)
- tx_delay = 2000;
- }
- if (rx_delay < 0)
- rx_delay = 0;
- if (tx_delay < 0)
- tx_delay = 0;
- dev->ports[port_num].rgmii_rx_val = rx_delay;
- dev->ports[port_num].rgmii_tx_val = tx_delay;
- }
- int ksz_switch_register(struct ksz_device *dev)
- {
- const struct ksz_chip_data *info;
- struct device_node *port, *ports;
- phy_interface_t interface;
- unsigned int port_num;
- int ret;
- int i;
- if (dev->pdata)
- dev->chip_id = dev->pdata->chip_id;
- dev->reset_gpio = devm_gpiod_get_optional(dev->dev, "reset",
- GPIOD_OUT_LOW);
- if (IS_ERR(dev->reset_gpio))
- return PTR_ERR(dev->reset_gpio);
- if (dev->reset_gpio) {
- gpiod_set_value_cansleep(dev->reset_gpio, 1);
- usleep_range(10000, 12000);
- gpiod_set_value_cansleep(dev->reset_gpio, 0);
- msleep(100);
- }
- mutex_init(&dev->dev_mutex);
- mutex_init(&dev->regmap_mutex);
- mutex_init(&dev->alu_mutex);
- mutex_init(&dev->vlan_mutex);
- ret = ksz_switch_detect(dev);
- if (ret)
- return ret;
- info = ksz_lookup_info(dev->chip_id);
- if (!info)
- return -ENODEV;
- /* Update the compatible info with the probed one */
- dev->info = info;
- dev_info(dev->dev, "found switch: %s, rev %i\n",
- dev->info->dev_name, dev->chip_rev);
- ret = ksz_check_device_id(dev);
- if (ret)
- return ret;
- dev->dev_ops = dev->info->ops;
- ret = dev->dev_ops->init(dev);
- if (ret)
- return ret;
- dev->ports = devm_kzalloc(dev->dev,
- dev->info->port_cnt * sizeof(struct ksz_port),
- GFP_KERNEL);
- if (!dev->ports)
- return -ENOMEM;
- for (i = 0; i < dev->info->port_cnt; i++) {
- spin_lock_init(&dev->ports[i].mib.stats64_lock);
- mutex_init(&dev->ports[i].mib.cnt_mutex);
- dev->ports[i].mib.counters =
- devm_kzalloc(dev->dev,
- sizeof(u64) * (dev->info->mib_cnt + 1),
- GFP_KERNEL);
- if (!dev->ports[i].mib.counters)
- return -ENOMEM;
- dev->ports[i].ksz_dev = dev;
- dev->ports[i].num = i;
- }
- /* set the real number of ports */
- dev->ds->num_ports = dev->info->port_cnt;
- /* Host port interface will be self detected, or specifically set in
- * device tree.
- */
- for (port_num = 0; port_num < dev->info->port_cnt; ++port_num)
- dev->ports[port_num].interface = PHY_INTERFACE_MODE_NA;
- if (dev->dev->of_node) {
- ret = of_get_phy_mode(dev->dev->of_node, &interface);
- if (ret == 0)
- dev->compat_interface = interface;
- ports = of_get_child_by_name(dev->dev->of_node, "ethernet-ports");
- if (!ports)
- ports = of_get_child_by_name(dev->dev->of_node, "ports");
- if (ports) {
- for_each_available_child_of_node(ports, port) {
- if (of_property_read_u32(port, "reg",
- &port_num))
- continue;
- if (!(dev->port_mask & BIT(port_num))) {
- of_node_put(port);
- of_node_put(ports);
- return -EINVAL;
- }
- of_get_phy_mode(port,
- &dev->ports[port_num].interface);
- ksz_parse_rgmii_delay(dev, port_num, port);
- }
- of_node_put(ports);
- }
- dev->synclko_125 = of_property_read_bool(dev->dev->of_node,
- "microchip,synclko-125");
- dev->synclko_disable = of_property_read_bool(dev->dev->of_node,
- "microchip,synclko-disable");
- if (dev->synclko_125 && dev->synclko_disable) {
- dev_err(dev->dev, "inconsistent synclko settings\n");
- return -EINVAL;
- }
- }
- ret = dsa_register_switch(dev->ds);
- if (ret) {
- dev->dev_ops->exit(dev);
- return ret;
- }
- /* Read MIB counters every 30 seconds to avoid overflow. */
- dev->mib_read_interval = msecs_to_jiffies(5000);
- /* Start the MIB timer. */
- schedule_delayed_work(&dev->mib_read, 0);
- return ret;
- }
- EXPORT_SYMBOL(ksz_switch_register);
- void ksz_switch_remove(struct ksz_device *dev)
- {
- /* timer started */
- if (dev->mib_read_interval) {
- dev->mib_read_interval = 0;
- cancel_delayed_work_sync(&dev->mib_read);
- }
- dev->dev_ops->exit(dev);
- dsa_unregister_switch(dev->ds);
- if (dev->reset_gpio)
- gpiod_set_value_cansleep(dev->reset_gpio, 1);
- }
- EXPORT_SYMBOL(ksz_switch_remove);
- MODULE_AUTHOR("Woojung Huh <[email protected]>");
- MODULE_DESCRIPTION("Microchip KSZ Series Switch DSA Driver");
- MODULE_LICENSE("GPL");
|