vsc9953.c 76 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2014 - 2015 Freescale Semiconductor, Inc.
  4. *
  5. * Driver for the Vitesse VSC9953 L2 Switch
  6. */
  7. #include <common.h>
  8. #include <command.h>
  9. #include <log.h>
  10. #include <asm/io.h>
  11. #include <asm/fsl_serdes.h>
  12. #include <fm_eth.h>
  13. #include <fsl_memac.h>
  14. #include <bitfield.h>
  15. #include <errno.h>
  16. #include <malloc.h>
  17. #include <vsc9953.h>
  18. #include <ethsw.h>
  19. #include <linux/delay.h>
  20. static struct vsc9953_info vsc9953_l2sw = {
  21. .port[0] = VSC9953_PORT_INFO_INITIALIZER(0),
  22. .port[1] = VSC9953_PORT_INFO_INITIALIZER(1),
  23. .port[2] = VSC9953_PORT_INFO_INITIALIZER(2),
  24. .port[3] = VSC9953_PORT_INFO_INITIALIZER(3),
  25. .port[4] = VSC9953_PORT_INFO_INITIALIZER(4),
  26. .port[5] = VSC9953_PORT_INFO_INITIALIZER(5),
  27. .port[6] = VSC9953_PORT_INFO_INITIALIZER(6),
  28. .port[7] = VSC9953_PORT_INFO_INITIALIZER(7),
  29. .port[8] = VSC9953_PORT_INFO_INITIALIZER(8),
  30. .port[9] = VSC9953_PORT_INFO_INITIALIZER(9),
  31. };
  32. void vsc9953_port_info_set_mdio(int port_no, struct mii_dev *bus)
  33. {
  34. if (!VSC9953_PORT_CHECK(port_no))
  35. return;
  36. vsc9953_l2sw.port[port_no].bus = bus;
  37. }
  38. void vsc9953_port_info_set_phy_address(int port_no, int address)
  39. {
  40. if (!VSC9953_PORT_CHECK(port_no))
  41. return;
  42. vsc9953_l2sw.port[port_no].phyaddr = address;
  43. }
  44. void vsc9953_port_info_set_phy_int(int port_no, phy_interface_t phy_int)
  45. {
  46. if (!VSC9953_PORT_CHECK(port_no))
  47. return;
  48. vsc9953_l2sw.port[port_no].enet_if = phy_int;
  49. }
  50. void vsc9953_port_enable(int port_no)
  51. {
  52. if (!VSC9953_PORT_CHECK(port_no))
  53. return;
  54. vsc9953_l2sw.port[port_no].enabled = 1;
  55. }
  56. void vsc9953_port_disable(int port_no)
  57. {
  58. if (!VSC9953_PORT_CHECK(port_no))
  59. return;
  60. vsc9953_l2sw.port[port_no].enabled = 0;
  61. }
  62. static void vsc9953_mdio_write(struct vsc9953_mii_mng *phyregs, int port_addr,
  63. int regnum, int value)
  64. {
  65. int timeout = 50000;
  66. out_le32(&phyregs->miimcmd, (0x1 << 31) | ((port_addr & 0x1f) << 25) |
  67. ((regnum & 0x1f) << 20) | ((value & 0xffff) << 4) |
  68. (0x1 << 1));
  69. asm("sync");
  70. while ((in_le32(&phyregs->miimstatus) & 0x8) && --timeout)
  71. udelay(1);
  72. if (timeout == 0)
  73. debug("Timeout waiting for MDIO write\n");
  74. }
  75. static int vsc9953_mdio_read(struct vsc9953_mii_mng *phyregs, int port_addr,
  76. int regnum)
  77. {
  78. int value = 0xFFFF;
  79. int timeout = 50000;
  80. while ((in_le32(&phyregs->miimstatus) & MIIMIND_OPR_PEND) && --timeout)
  81. udelay(1);
  82. if (timeout == 0) {
  83. debug("Timeout waiting for MDIO operation to finish\n");
  84. return value;
  85. }
  86. /* Put the address of the phy, and the register
  87. * number into MIICMD
  88. */
  89. out_le32(&phyregs->miimcmd, (0x1 << 31) | ((port_addr & 0x1f) << 25) |
  90. ((regnum & 0x1f) << 20) | ((value & 0xffff) << 4) |
  91. (0x2 << 1));
  92. timeout = 50000;
  93. /* Wait for the the indication that the read is done */
  94. while ((in_le32(&phyregs->miimstatus) & 0x8) && --timeout)
  95. udelay(1);
  96. if (timeout == 0)
  97. debug("Timeout waiting for MDIO read\n");
  98. /* Grab the value read from the PHY */
  99. value = in_le32(&phyregs->miimdata);
  100. if ((value & 0x00030000) == 0)
  101. return value & 0x0000ffff;
  102. return value;
  103. }
  104. static int init_phy(struct eth_device *dev)
  105. {
  106. struct vsc9953_port_info *l2sw_port = dev->priv;
  107. struct phy_device *phydev = NULL;
  108. #ifdef CONFIG_PHYLIB
  109. if (!l2sw_port->bus)
  110. return 0;
  111. phydev = phy_connect(l2sw_port->bus, l2sw_port->phyaddr, dev,
  112. l2sw_port->enet_if);
  113. if (!phydev) {
  114. printf("Failed to connect\n");
  115. return -1;
  116. }
  117. phydev->supported &= SUPPORTED_10baseT_Half |
  118. SUPPORTED_10baseT_Full |
  119. SUPPORTED_100baseT_Half |
  120. SUPPORTED_100baseT_Full |
  121. SUPPORTED_1000baseT_Full;
  122. phydev->advertising = phydev->supported;
  123. l2sw_port->phydev = phydev;
  124. phy_config(phydev);
  125. #endif
  126. return 0;
  127. }
  128. static int vsc9953_port_init(int port_no)
  129. {
  130. struct eth_device *dev;
  131. /* Internal ports never have a PHY */
  132. if (VSC9953_INTERNAL_PORT_CHECK(port_no))
  133. return 0;
  134. /* alloc eth device */
  135. dev = (struct eth_device *)calloc(1, sizeof(struct eth_device));
  136. if (!dev)
  137. return -ENOMEM;
  138. sprintf(dev->name, "SW@PORT%d", port_no);
  139. dev->priv = &vsc9953_l2sw.port[port_no];
  140. dev->init = NULL;
  141. dev->halt = NULL;
  142. dev->send = NULL;
  143. dev->recv = NULL;
  144. if (init_phy(dev)) {
  145. free(dev);
  146. return -ENODEV;
  147. }
  148. return 0;
  149. }
  150. static int vsc9953_vlan_table_poll_idle(void)
  151. {
  152. struct vsc9953_analyzer *l2ana_reg;
  153. int timeout;
  154. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  155. VSC9953_ANA_OFFSET);
  156. timeout = 50000;
  157. while (((in_le32(&l2ana_reg->ana_tables.vlan_access) &
  158. VSC9953_VLAN_CMD_MASK) != VSC9953_VLAN_CMD_IDLE) && --timeout)
  159. udelay(1);
  160. return timeout ? 0 : -EBUSY;
  161. }
  162. #ifdef CONFIG_CMD_ETHSW
  163. /* Add/remove a port to/from a VLAN */
  164. static void vsc9953_vlan_table_membership_set(int vid, u32 port_no, u8 add)
  165. {
  166. u32 val;
  167. struct vsc9953_analyzer *l2ana_reg;
  168. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  169. VSC9953_ANA_OFFSET);
  170. if (vsc9953_vlan_table_poll_idle() < 0) {
  171. debug("VLAN table timeout\n");
  172. return;
  173. }
  174. val = in_le32(&l2ana_reg->ana_tables.vlan_tidx);
  175. val = bitfield_replace_by_mask(val, VSC9953_ANA_TBL_VID_MASK, vid);
  176. out_le32(&l2ana_reg->ana_tables.vlan_tidx, val);
  177. clrsetbits_le32(&l2ana_reg->ana_tables.vlan_access,
  178. VSC9953_VLAN_CMD_MASK, VSC9953_VLAN_CMD_READ);
  179. if (vsc9953_vlan_table_poll_idle() < 0) {
  180. debug("VLAN table timeout\n");
  181. return;
  182. }
  183. val = in_le32(&l2ana_reg->ana_tables.vlan_tidx);
  184. val = bitfield_replace_by_mask(val, VSC9953_ANA_TBL_VID_MASK, vid);
  185. out_le32(&l2ana_reg->ana_tables.vlan_tidx, val);
  186. val = in_le32(&l2ana_reg->ana_tables.vlan_access);
  187. if (!add) {
  188. val = bitfield_replace_by_mask(val, VSC9953_VLAN_CMD_MASK,
  189. VSC9953_VLAN_CMD_WRITE) &
  190. ~(bitfield_replace_by_mask(0, VSC9953_VLAN_PORT_MASK,
  191. (1 << port_no)));
  192. ;
  193. } else {
  194. val = bitfield_replace_by_mask(val, VSC9953_VLAN_CMD_MASK,
  195. VSC9953_VLAN_CMD_WRITE) |
  196. bitfield_replace_by_mask(0, VSC9953_VLAN_PORT_MASK,
  197. (1 << port_no));
  198. }
  199. out_le32(&l2ana_reg->ana_tables.vlan_access, val);
  200. /* wait for VLAN table command to flush */
  201. if (vsc9953_vlan_table_poll_idle() < 0) {
  202. debug("VLAN table timeout\n");
  203. return;
  204. }
  205. }
  206. /* show VLAN membership for a port */
  207. static void vsc9953_vlan_membership_show(int port_no)
  208. {
  209. u32 val;
  210. struct vsc9953_analyzer *l2ana_reg;
  211. u32 vid;
  212. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  213. VSC9953_ANA_OFFSET);
  214. printf("Port %d VLAN membership: ", port_no);
  215. for (vid = 0; vid < VSC9953_MAX_VLAN; vid++) {
  216. if (vsc9953_vlan_table_poll_idle() < 0) {
  217. debug("VLAN table timeout\n");
  218. return;
  219. }
  220. val = in_le32(&l2ana_reg->ana_tables.vlan_tidx);
  221. val = bitfield_replace_by_mask(val, VSC9953_ANA_TBL_VID_MASK,
  222. vid);
  223. out_le32(&l2ana_reg->ana_tables.vlan_tidx, val);
  224. clrsetbits_le32(&l2ana_reg->ana_tables.vlan_access,
  225. VSC9953_VLAN_CMD_MASK, VSC9953_VLAN_CMD_READ);
  226. if (vsc9953_vlan_table_poll_idle() < 0) {
  227. debug("VLAN table timeout\n");
  228. return;
  229. }
  230. val = in_le32(&l2ana_reg->ana_tables.vlan_access);
  231. if (bitfield_extract_by_mask(val, VSC9953_VLAN_PORT_MASK) &
  232. (1 << port_no))
  233. printf("%d ", vid);
  234. }
  235. printf("\n");
  236. }
  237. #endif
  238. /* vlan table set/clear all membership of vid */
  239. static void vsc9953_vlan_table_membership_all_set(int vid, int set_member)
  240. {
  241. uint val;
  242. struct vsc9953_analyzer *l2ana_reg;
  243. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  244. VSC9953_ANA_OFFSET);
  245. if (vsc9953_vlan_table_poll_idle() < 0) {
  246. debug("VLAN table timeout\n");
  247. return;
  248. }
  249. /* read current vlan configuration */
  250. val = in_le32(&l2ana_reg->ana_tables.vlan_tidx);
  251. out_le32(&l2ana_reg->ana_tables.vlan_tidx,
  252. bitfield_replace_by_mask(val, VSC9953_ANA_TBL_VID_MASK, vid));
  253. clrsetbits_le32(&l2ana_reg->ana_tables.vlan_access,
  254. VSC9953_VLAN_CMD_MASK, VSC9953_VLAN_CMD_READ);
  255. if (vsc9953_vlan_table_poll_idle() < 0) {
  256. debug("VLAN table timeout\n");
  257. return;
  258. }
  259. val = in_le32(&l2ana_reg->ana_tables.vlan_tidx);
  260. out_le32(&l2ana_reg->ana_tables.vlan_tidx,
  261. bitfield_replace_by_mask(val, VSC9953_ANA_TBL_VID_MASK, vid));
  262. clrsetbits_le32(&l2ana_reg->ana_tables.vlan_access,
  263. VSC9953_VLAN_PORT_MASK | VSC9953_VLAN_CMD_MASK,
  264. VSC9953_VLAN_CMD_WRITE |
  265. (set_member ? VSC9953_VLAN_PORT_MASK : 0));
  266. }
  267. #ifdef CONFIG_CMD_ETHSW
  268. /* Get PVID of a VSC9953 port */
  269. static int vsc9953_port_vlan_pvid_get(int port_nr, int *pvid)
  270. {
  271. u32 val;
  272. struct vsc9953_analyzer *l2ana_reg;
  273. /* Administrative down */
  274. if (!vsc9953_l2sw.port[port_nr].enabled) {
  275. printf("Port %d is administrative down\n", port_nr);
  276. return -1;
  277. }
  278. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  279. VSC9953_ANA_OFFSET);
  280. /* Get ingress PVID */
  281. val = in_le32(&l2ana_reg->port[port_nr].vlan_cfg);
  282. *pvid = bitfield_extract_by_mask(val, VSC9953_VLAN_CFG_VID_MASK);
  283. return 0;
  284. }
  285. #endif
  286. /* Set PVID for a VSC9953 port */
  287. static void vsc9953_port_vlan_pvid_set(int port_no, int pvid)
  288. {
  289. uint val;
  290. struct vsc9953_analyzer *l2ana_reg;
  291. struct vsc9953_rew_reg *l2rew_reg;
  292. /* Administrative down */
  293. if (!vsc9953_l2sw.port[port_no].enabled) {
  294. printf("Port %d is administrative down\n", port_no);
  295. return;
  296. }
  297. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  298. VSC9953_ANA_OFFSET);
  299. l2rew_reg = (struct vsc9953_rew_reg *)(VSC9953_OFFSET +
  300. VSC9953_REW_OFFSET);
  301. /* Set PVID on ingress */
  302. val = in_le32(&l2ana_reg->port[port_no].vlan_cfg);
  303. val = bitfield_replace_by_mask(val, VSC9953_VLAN_CFG_VID_MASK, pvid);
  304. out_le32(&l2ana_reg->port[port_no].vlan_cfg, val);
  305. /* Set PVID on egress */
  306. val = in_le32(&l2rew_reg->port[port_no].port_vlan_cfg);
  307. val = bitfield_replace_by_mask(val, VSC9953_PORT_VLAN_CFG_VID_MASK,
  308. pvid);
  309. out_le32(&l2rew_reg->port[port_no].port_vlan_cfg, val);
  310. }
  311. static void vsc9953_port_all_vlan_pvid_set(int pvid)
  312. {
  313. int i;
  314. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  315. vsc9953_port_vlan_pvid_set(i, pvid);
  316. }
  317. /* Enable/disable vlan aware of a VSC9953 port */
  318. static void vsc9953_port_vlan_aware_set(int port_no, int enabled)
  319. {
  320. struct vsc9953_analyzer *l2ana_reg;
  321. /* Administrative down */
  322. if (!vsc9953_l2sw.port[port_no].enabled) {
  323. printf("Port %d is administrative down\n", port_no);
  324. return;
  325. }
  326. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  327. VSC9953_ANA_OFFSET);
  328. if (enabled)
  329. setbits_le32(&l2ana_reg->port[port_no].vlan_cfg,
  330. VSC9953_VLAN_CFG_AWARE_ENA);
  331. else
  332. clrbits_le32(&l2ana_reg->port[port_no].vlan_cfg,
  333. VSC9953_VLAN_CFG_AWARE_ENA);
  334. }
  335. /* Set all VSC9953 ports' vlan aware */
  336. static void vsc9953_port_all_vlan_aware_set(int enabled)
  337. {
  338. int i;
  339. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  340. vsc9953_port_vlan_aware_set(i, enabled);
  341. }
  342. /* Enable/disable vlan pop count of a VSC9953 port */
  343. static void vsc9953_port_vlan_popcnt_set(int port_no, int popcnt)
  344. {
  345. uint val;
  346. struct vsc9953_analyzer *l2ana_reg;
  347. /* Administrative down */
  348. if (!vsc9953_l2sw.port[port_no].enabled) {
  349. printf("Port %d is administrative down\n", port_no);
  350. return;
  351. }
  352. if (popcnt > 3 || popcnt < 0) {
  353. printf("Invalid pop count value: %d\n", port_no);
  354. return;
  355. }
  356. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  357. VSC9953_ANA_OFFSET);
  358. val = in_le32(&l2ana_reg->port[port_no].vlan_cfg);
  359. val = bitfield_replace_by_mask(val, VSC9953_VLAN_CFG_POP_CNT_MASK,
  360. popcnt);
  361. out_le32(&l2ana_reg->port[port_no].vlan_cfg, val);
  362. }
  363. /* Set all VSC9953 ports' pop count */
  364. static void vsc9953_port_all_vlan_poncnt_set(int popcnt)
  365. {
  366. int i;
  367. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  368. vsc9953_port_vlan_popcnt_set(i, popcnt);
  369. }
  370. /* Enable/disable learning for frames dropped due to ingress filtering */
  371. static void vsc9953_vlan_ingr_fltr_learn_drop(int enable)
  372. {
  373. struct vsc9953_analyzer *l2ana_reg;
  374. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  375. VSC9953_ANA_OFFSET);
  376. if (enable)
  377. setbits_le32(&l2ana_reg->ana.adv_learn, VSC9953_VLAN_CHK);
  378. else
  379. clrbits_le32(&l2ana_reg->ana.adv_learn, VSC9953_VLAN_CHK);
  380. }
  381. enum aggr_code_mode {
  382. AGGR_CODE_RAND = 0,
  383. AGGR_CODE_ALL, /* S/D MAC, IPv4 S/D IP, IPv6 Flow Label, S/D PORT */
  384. };
  385. /* Set aggregation code generation mode */
  386. static int vsc9953_aggr_code_set(enum aggr_code_mode ac)
  387. {
  388. int rc;
  389. struct vsc9953_analyzer *l2ana_reg;
  390. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  391. VSC9953_ANA_OFFSET);
  392. switch (ac) {
  393. case AGGR_CODE_RAND:
  394. clrsetbits_le32(&l2ana_reg->common.aggr_cfg,
  395. VSC9953_AC_DMAC_ENA | VSC9953_AC_SMAC_ENA |
  396. VSC9953_AC_IP6_LBL_ENA |
  397. VSC9953_AC_IP6_TCPUDP_ENA |
  398. VSC9953_AC_IP4_SIPDIP_ENA |
  399. VSC9953_AC_IP4_TCPUDP_ENA, VSC9953_AC_RND_ENA);
  400. rc = 0;
  401. break;
  402. case AGGR_CODE_ALL:
  403. clrsetbits_le32(&l2ana_reg->common.aggr_cfg, VSC9953_AC_RND_ENA,
  404. VSC9953_AC_DMAC_ENA | VSC9953_AC_SMAC_ENA |
  405. VSC9953_AC_IP6_LBL_ENA |
  406. VSC9953_AC_IP6_TCPUDP_ENA |
  407. VSC9953_AC_IP4_SIPDIP_ENA |
  408. VSC9953_AC_IP4_TCPUDP_ENA);
  409. rc = 0;
  410. break;
  411. default:
  412. /* unknown mode for aggregation code */
  413. rc = -EINVAL;
  414. }
  415. return rc;
  416. }
  417. /* Egress untag modes of a VSC9953 port */
  418. enum egress_untag_mode {
  419. EGRESS_UNTAG_ALL = 0,
  420. EGRESS_UNTAG_PVID_AND_ZERO,
  421. EGRESS_UNTAG_ZERO,
  422. EGRESS_UNTAG_NONE,
  423. };
  424. #ifdef CONFIG_CMD_ETHSW
  425. /* Get egress tagging configuration for a VSC9953 port */
  426. static int vsc9953_port_vlan_egr_untag_get(int port_no,
  427. enum egress_untag_mode *mode)
  428. {
  429. u32 val;
  430. struct vsc9953_rew_reg *l2rew_reg;
  431. /* Administrative down */
  432. if (!vsc9953_l2sw.port[port_no].enabled) {
  433. printf("Port %d is administrative down\n", port_no);
  434. return -1;
  435. }
  436. l2rew_reg = (struct vsc9953_rew_reg *)(VSC9953_OFFSET +
  437. VSC9953_REW_OFFSET);
  438. val = in_le32(&l2rew_reg->port[port_no].port_tag_cfg);
  439. switch (val & VSC9953_TAG_CFG_MASK) {
  440. case VSC9953_TAG_CFG_NONE:
  441. *mode = EGRESS_UNTAG_ALL;
  442. return 0;
  443. case VSC9953_TAG_CFG_ALL_BUT_PVID_ZERO:
  444. *mode = EGRESS_UNTAG_PVID_AND_ZERO;
  445. return 0;
  446. case VSC9953_TAG_CFG_ALL_BUT_ZERO:
  447. *mode = EGRESS_UNTAG_ZERO;
  448. return 0;
  449. case VSC9953_TAG_CFG_ALL:
  450. *mode = EGRESS_UNTAG_NONE;
  451. return 0;
  452. default:
  453. printf("Unknown egress tagging configuration for port %d\n",
  454. port_no);
  455. return -1;
  456. }
  457. }
  458. /* Show egress tagging configuration for a VSC9953 port */
  459. static void vsc9953_port_vlan_egr_untag_show(int port_no)
  460. {
  461. enum egress_untag_mode mode;
  462. if (vsc9953_port_vlan_egr_untag_get(port_no, &mode)) {
  463. printf("%7d\t%17s\n", port_no, "-");
  464. return;
  465. }
  466. printf("%7d\t", port_no);
  467. switch (mode) {
  468. case EGRESS_UNTAG_ALL:
  469. printf("%17s\n", "all");
  470. break;
  471. case EGRESS_UNTAG_NONE:
  472. printf("%17s\n", "none");
  473. break;
  474. case EGRESS_UNTAG_PVID_AND_ZERO:
  475. printf("%17s\n", "PVID and 0");
  476. break;
  477. case EGRESS_UNTAG_ZERO:
  478. printf("%17s\n", "0");
  479. break;
  480. default:
  481. printf("%17s\n", "-");
  482. }
  483. }
  484. #endif
  485. static void vsc9953_port_vlan_egr_untag_set(int port_no,
  486. enum egress_untag_mode mode)
  487. {
  488. struct vsc9953_rew_reg *l2rew_reg;
  489. /* Administrative down */
  490. if (!vsc9953_l2sw.port[port_no].enabled) {
  491. printf("Port %d is administrative down\n", port_no);
  492. return;
  493. }
  494. l2rew_reg = (struct vsc9953_rew_reg *)(VSC9953_OFFSET +
  495. VSC9953_REW_OFFSET);
  496. switch (mode) {
  497. case EGRESS_UNTAG_ALL:
  498. clrsetbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
  499. VSC9953_TAG_CFG_MASK, VSC9953_TAG_CFG_NONE);
  500. break;
  501. case EGRESS_UNTAG_PVID_AND_ZERO:
  502. clrsetbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
  503. VSC9953_TAG_CFG_MASK,
  504. VSC9953_TAG_CFG_ALL_BUT_PVID_ZERO);
  505. break;
  506. case EGRESS_UNTAG_ZERO:
  507. clrsetbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
  508. VSC9953_TAG_CFG_MASK,
  509. VSC9953_TAG_CFG_ALL_BUT_ZERO);
  510. break;
  511. case EGRESS_UNTAG_NONE:
  512. clrsetbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
  513. VSC9953_TAG_CFG_MASK, VSC9953_TAG_CFG_ALL);
  514. break;
  515. default:
  516. printf("Unknown untag mode for port %d\n", port_no);
  517. }
  518. }
  519. static void vsc9953_port_all_vlan_egress_untagged_set(
  520. enum egress_untag_mode mode)
  521. {
  522. int i;
  523. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  524. vsc9953_port_vlan_egr_untag_set(i, mode);
  525. }
  526. static int vsc9953_autoage_time_set(int age_period)
  527. {
  528. u32 autoage;
  529. struct vsc9953_analyzer *l2ana_reg;
  530. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  531. VSC9953_ANA_OFFSET);
  532. if (age_period < 0 || age_period > VSC9953_AUTOAGE_PERIOD_MASK)
  533. return -EINVAL;
  534. autoage = bitfield_replace_by_mask(in_le32(&l2ana_reg->ana.auto_age),
  535. VSC9953_AUTOAGE_PERIOD_MASK,
  536. age_period);
  537. out_le32(&l2ana_reg->ana.auto_age, autoage);
  538. return 0;
  539. }
  540. #ifdef CONFIG_CMD_ETHSW
  541. /* Enable/disable status of a VSC9953 port */
  542. static void vsc9953_port_status_set(int port_no, u8 enabled)
  543. {
  544. struct vsc9953_qsys_reg *l2qsys_reg;
  545. /* Administrative down */
  546. if (!vsc9953_l2sw.port[port_no].enabled)
  547. return;
  548. l2qsys_reg = (struct vsc9953_qsys_reg *)(VSC9953_OFFSET +
  549. VSC9953_QSYS_OFFSET);
  550. if (enabled)
  551. setbits_le32(&l2qsys_reg->sys.switch_port_mode[port_no],
  552. VSC9953_PORT_ENA);
  553. else
  554. clrbits_le32(&l2qsys_reg->sys.switch_port_mode[port_no],
  555. VSC9953_PORT_ENA);
  556. }
  557. /* Start autonegotiation for a VSC9953 PHY */
  558. static void vsc9953_phy_autoneg(int port_no)
  559. {
  560. if (!vsc9953_l2sw.port[port_no].phydev)
  561. return;
  562. if (vsc9953_l2sw.port[port_no].phydev->drv->startup(
  563. vsc9953_l2sw.port[port_no].phydev))
  564. printf("Failed to start PHY for port %d\n", port_no);
  565. }
  566. /* Print a VSC9953 port's configuration */
  567. static void vsc9953_port_config_show(int port_no)
  568. {
  569. int speed;
  570. int duplex;
  571. int link;
  572. u8 enabled;
  573. u32 val;
  574. struct vsc9953_qsys_reg *l2qsys_reg;
  575. l2qsys_reg = (struct vsc9953_qsys_reg *)(VSC9953_OFFSET +
  576. VSC9953_QSYS_OFFSET);
  577. val = in_le32(&l2qsys_reg->sys.switch_port_mode[port_no]);
  578. enabled = vsc9953_l2sw.port[port_no].enabled &&
  579. (val & VSC9953_PORT_ENA);
  580. /* internal ports (8 and 9) are fixed */
  581. if (VSC9953_INTERNAL_PORT_CHECK(port_no)) {
  582. link = 1;
  583. speed = SPEED_2500;
  584. duplex = DUPLEX_FULL;
  585. } else {
  586. if (vsc9953_l2sw.port[port_no].phydev) {
  587. link = vsc9953_l2sw.port[port_no].phydev->link;
  588. speed = vsc9953_l2sw.port[port_no].phydev->speed;
  589. duplex = vsc9953_l2sw.port[port_no].phydev->duplex;
  590. } else {
  591. link = -1;
  592. speed = -1;
  593. duplex = -1;
  594. }
  595. }
  596. printf("%8d ", port_no);
  597. printf("%8s ", enabled == 1 ? "enabled" : "disabled");
  598. printf("%8s ", link == 1 ? "up" : "down");
  599. switch (speed) {
  600. case SPEED_10:
  601. printf("%8d ", 10);
  602. break;
  603. case SPEED_100:
  604. printf("%8d ", 100);
  605. break;
  606. case SPEED_1000:
  607. printf("%8d ", 1000);
  608. break;
  609. case SPEED_2500:
  610. printf("%8d ", 2500);
  611. break;
  612. case SPEED_10000:
  613. printf("%8d ", 10000);
  614. break;
  615. default:
  616. printf("%8s ", "-");
  617. }
  618. printf("%8s\n", duplex == DUPLEX_FULL ? "full" : "half");
  619. }
  620. /* Show VSC9953 ports' statistics */
  621. static void vsc9953_port_statistics_show(int port_no)
  622. {
  623. u32 rx_val;
  624. u32 tx_val;
  625. struct vsc9953_system_reg *l2sys_reg;
  626. /* Administrative down */
  627. if (!vsc9953_l2sw.port[port_no].enabled) {
  628. printf("Port %d is administrative down\n", port_no);
  629. return;
  630. }
  631. l2sys_reg = (struct vsc9953_system_reg *)(VSC9953_OFFSET +
  632. VSC9953_SYS_OFFSET);
  633. printf("Statistics for L2 Switch port %d:\n", port_no);
  634. /* Set counter view for our port */
  635. out_le32(&l2sys_reg->sys.stat_cfg, port_no);
  636. #define VSC9953_STATS_PRINTF "%-15s %10u"
  637. /* Get number of Rx and Tx frames */
  638. rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_short) +
  639. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_frag) +
  640. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_jabber) +
  641. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_long) +
  642. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_64) +
  643. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_65_127) +
  644. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_128_255) +
  645. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_256_511) +
  646. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_512_1023) +
  647. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_1024_1526) +
  648. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_jumbo);
  649. tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_64) +
  650. in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_65_127) +
  651. in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_128_255) +
  652. in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_256_511) +
  653. in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_512_1023) +
  654. in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_1024_1526) +
  655. in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_jumbo);
  656. printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
  657. "Rx frames:", rx_val, "Tx frames:", tx_val);
  658. /* Get number of Rx and Tx bytes */
  659. rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_oct);
  660. tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_oct);
  661. printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
  662. "Rx bytes:", rx_val, "Tx bytes:", tx_val);
  663. /* Get number of Rx frames received ok and Tx frames sent ok */
  664. rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_0) +
  665. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_1) +
  666. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_2) +
  667. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_3) +
  668. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_4) +
  669. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_5) +
  670. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_6) +
  671. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_7) +
  672. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_0) +
  673. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_1) +
  674. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_2) +
  675. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_3) +
  676. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_4) +
  677. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_5) +
  678. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_6) +
  679. in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_7);
  680. tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_64) +
  681. in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_65_127) +
  682. in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_128_255) +
  683. in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_256_511) +
  684. in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_512_1023) +
  685. in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_1024_1526) +
  686. in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_jumbo);
  687. printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
  688. "Rx frames ok:", rx_val, "Tx frames ok:", tx_val);
  689. /* Get number of Rx and Tx unicast frames */
  690. rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_uc);
  691. tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_uc);
  692. printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
  693. "Rx unicast:", rx_val, "Tx unicast:", tx_val);
  694. /* Get number of Rx and Tx broadcast frames */
  695. rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_bc);
  696. tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_bc);
  697. printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
  698. "Rx broadcast:", rx_val, "Tx broadcast:", tx_val);
  699. /* Get number of Rx and Tx frames of 64B */
  700. rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_64);
  701. tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_64);
  702. printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
  703. "Rx 64B:", rx_val, "Tx 64B:", tx_val);
  704. /* Get number of Rx and Tx frames with sizes between 65B and 127B */
  705. rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_65_127);
  706. tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_65_127);
  707. printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
  708. "Rx 65B-127B:", rx_val, "Tx 65B-127B:", tx_val);
  709. /* Get number of Rx and Tx frames with sizes between 128B and 255B */
  710. rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_128_255);
  711. tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_128_255);
  712. printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
  713. "Rx 128B-255B:", rx_val, "Tx 128B-255B:", tx_val);
  714. /* Get number of Rx and Tx frames with sizes between 256B and 511B */
  715. rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_256_511);
  716. tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_256_511);
  717. printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
  718. "Rx 256B-511B:", rx_val, "Tx 256B-511B:", tx_val);
  719. /* Get number of Rx and Tx frames with sizes between 512B and 1023B */
  720. rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_512_1023);
  721. tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_512_1023);
  722. printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
  723. "Rx 512B-1023B:", rx_val, "Tx 512B-1023B:", tx_val);
  724. /* Get number of Rx and Tx frames with sizes between 1024B and 1526B */
  725. rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_1024_1526);
  726. tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_1024_1526);
  727. printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
  728. "Rx 1024B-1526B:", rx_val, "Tx 1024B-1526B:", tx_val);
  729. /* Get number of Rx and Tx jumbo frames */
  730. rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_jumbo);
  731. tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_jumbo);
  732. printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
  733. "Rx jumbo:", rx_val, "Tx jumbo:", tx_val);
  734. /* Get number of Rx and Tx dropped frames */
  735. rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_cat_drop) +
  736. in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_tail) +
  737. in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_0) +
  738. in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_1) +
  739. in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_2) +
  740. in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_3) +
  741. in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_4) +
  742. in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_5) +
  743. in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_6) +
  744. in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_7) +
  745. in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_0) +
  746. in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_1) +
  747. in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_2) +
  748. in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_3) +
  749. in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_4) +
  750. in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_5) +
  751. in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_6) +
  752. in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_7);
  753. tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_drop) +
  754. in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_aged);
  755. printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
  756. "Rx drops:", rx_val, "Tx drops:", tx_val);
  757. /*
  758. * Get number of Rx frames with CRC or alignment errors
  759. * and number of detected Tx collisions
  760. */
  761. rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_crc);
  762. tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_col);
  763. printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
  764. "Rx CRC&align:", rx_val, "Tx coll:", tx_val);
  765. /*
  766. * Get number of Rx undersized frames and
  767. * number of Tx aged frames
  768. */
  769. rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_short);
  770. tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_aged);
  771. printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
  772. "Rx undersize:", rx_val, "Tx aged:", tx_val);
  773. /* Get number of Rx oversized frames */
  774. rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_long);
  775. printf(VSC9953_STATS_PRINTF"\n", "Rx oversized:", rx_val);
  776. /* Get number of Rx fragmented frames */
  777. rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_frag);
  778. printf(VSC9953_STATS_PRINTF"\n", "Rx fragments:", rx_val);
  779. /* Get number of Rx jabber errors */
  780. rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_jabber);
  781. printf(VSC9953_STATS_PRINTF"\n", "Rx jabbers:", rx_val);
  782. /*
  783. * Get number of Rx frames filtered due to classification rules or
  784. * no destination ports
  785. */
  786. rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_cat_drop) +
  787. in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_local);
  788. printf(VSC9953_STATS_PRINTF"\n", "Rx filtered:", rx_val);
  789. printf("\n");
  790. }
  791. /* Clear statistics for a VSC9953 port */
  792. static void vsc9953_port_statistics_clear(int port_no)
  793. {
  794. struct vsc9953_system_reg *l2sys_reg;
  795. /* Administrative down */
  796. if (!vsc9953_l2sw.port[port_no].enabled) {
  797. printf("Port %d is administrative down\n", port_no);
  798. return;
  799. }
  800. l2sys_reg = (struct vsc9953_system_reg *)(VSC9953_OFFSET +
  801. VSC9953_SYS_OFFSET);
  802. /* Clear all counter groups for our ports */
  803. out_le32(&l2sys_reg->sys.stat_cfg, port_no |
  804. VSC9953_STAT_CLEAR_RX | VSC9953_STAT_CLEAR_TX |
  805. VSC9953_STAT_CLEAR_DR);
  806. }
  807. enum port_learn_mode {
  808. PORT_LEARN_NONE,
  809. PORT_LEARN_AUTO
  810. };
  811. /* Set learning configuration for a VSC9953 port */
  812. static void vsc9953_port_learn_mode_set(int port_no, enum port_learn_mode mode)
  813. {
  814. struct vsc9953_analyzer *l2ana_reg;
  815. /* Administrative down */
  816. if (!vsc9953_l2sw.port[port_no].enabled) {
  817. printf("Port %d is administrative down\n", port_no);
  818. return;
  819. }
  820. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  821. VSC9953_ANA_OFFSET);
  822. switch (mode) {
  823. case PORT_LEARN_NONE:
  824. clrbits_le32(&l2ana_reg->port[port_no].port_cfg,
  825. VSC9953_PORT_CFG_LEARN_DROP |
  826. VSC9953_PORT_CFG_LEARN_CPU |
  827. VSC9953_PORT_CFG_LEARN_AUTO |
  828. VSC9953_PORT_CFG_LEARN_ENA);
  829. break;
  830. case PORT_LEARN_AUTO:
  831. clrsetbits_le32(&l2ana_reg->port[port_no].port_cfg,
  832. VSC9953_PORT_CFG_LEARN_DROP |
  833. VSC9953_PORT_CFG_LEARN_CPU,
  834. VSC9953_PORT_CFG_LEARN_ENA |
  835. VSC9953_PORT_CFG_LEARN_AUTO);
  836. break;
  837. default:
  838. printf("Unknown learn mode for port %d\n", port_no);
  839. }
  840. }
  841. /* Get learning configuration for a VSC9953 port */
  842. static int vsc9953_port_learn_mode_get(int port_no, enum port_learn_mode *mode)
  843. {
  844. u32 val;
  845. struct vsc9953_analyzer *l2ana_reg;
  846. /* Administrative down */
  847. if (!vsc9953_l2sw.port[port_no].enabled) {
  848. printf("Port %d is administrative down\n", port_no);
  849. return -1;
  850. }
  851. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  852. VSC9953_ANA_OFFSET);
  853. /* For now we only support HW learning (auto) and no learning */
  854. val = in_le32(&l2ana_reg->port[port_no].port_cfg);
  855. if ((val & (VSC9953_PORT_CFG_LEARN_ENA |
  856. VSC9953_PORT_CFG_LEARN_AUTO)) ==
  857. (VSC9953_PORT_CFG_LEARN_ENA | VSC9953_PORT_CFG_LEARN_AUTO))
  858. *mode = PORT_LEARN_AUTO;
  859. else
  860. *mode = PORT_LEARN_NONE;
  861. return 0;
  862. }
  863. /* wait for FDB to become available */
  864. static int vsc9953_mac_table_poll_idle(void)
  865. {
  866. struct vsc9953_analyzer *l2ana_reg;
  867. u32 timeout;
  868. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  869. VSC9953_ANA_OFFSET);
  870. timeout = 50000;
  871. while (((in_le32(&l2ana_reg->ana_tables.mac_access) &
  872. VSC9953_MAC_CMD_MASK) !=
  873. VSC9953_MAC_CMD_IDLE) && --timeout)
  874. udelay(1);
  875. return timeout ? 0 : -EBUSY;
  876. }
  877. /* enum describing available commands for the MAC table */
  878. enum mac_table_cmd {
  879. MAC_TABLE_READ,
  880. MAC_TABLE_LOOKUP,
  881. MAC_TABLE_WRITE,
  882. MAC_TABLE_LEARN,
  883. MAC_TABLE_FORGET,
  884. MAC_TABLE_GET_NEXT,
  885. MAC_TABLE_AGE,
  886. };
  887. /* Issues a command to the FDB table */
  888. static int vsc9953_mac_table_cmd(enum mac_table_cmd cmd)
  889. {
  890. struct vsc9953_analyzer *l2ana_reg;
  891. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  892. VSC9953_ANA_OFFSET);
  893. switch (cmd) {
  894. case MAC_TABLE_READ:
  895. clrsetbits_le32(&l2ana_reg->ana_tables.mac_access,
  896. VSC9953_MAC_CMD_MASK | VSC9953_MAC_CMD_VALID,
  897. VSC9953_MAC_CMD_READ);
  898. break;
  899. case MAC_TABLE_LOOKUP:
  900. clrsetbits_le32(&l2ana_reg->ana_tables.mac_access,
  901. VSC9953_MAC_CMD_MASK, VSC9953_MAC_CMD_READ |
  902. VSC9953_MAC_CMD_VALID);
  903. break;
  904. case MAC_TABLE_WRITE:
  905. clrsetbits_le32(&l2ana_reg->ana_tables.mac_access,
  906. VSC9953_MAC_CMD_MASK |
  907. VSC9953_MAC_ENTRYTYPE_MASK,
  908. VSC9953_MAC_CMD_WRITE |
  909. VSC9953_MAC_ENTRYTYPE_LOCKED);
  910. break;
  911. case MAC_TABLE_LEARN:
  912. clrsetbits_le32(&l2ana_reg->ana_tables.mac_access,
  913. VSC9953_MAC_CMD_MASK |
  914. VSC9953_MAC_ENTRYTYPE_MASK,
  915. VSC9953_MAC_CMD_LEARN |
  916. VSC9953_MAC_ENTRYTYPE_LOCKED |
  917. VSC9953_MAC_CMD_VALID);
  918. break;
  919. case MAC_TABLE_FORGET:
  920. clrsetbits_le32(&l2ana_reg->ana_tables.mac_access,
  921. VSC9953_MAC_CMD_MASK |
  922. VSC9953_MAC_ENTRYTYPE_MASK,
  923. VSC9953_MAC_CMD_FORGET);
  924. break;
  925. case MAC_TABLE_GET_NEXT:
  926. clrsetbits_le32(&l2ana_reg->ana_tables.mac_access,
  927. VSC9953_MAC_CMD_MASK |
  928. VSC9953_MAC_ENTRYTYPE_MASK,
  929. VSC9953_MAC_CMD_NEXT);
  930. break;
  931. case MAC_TABLE_AGE:
  932. clrsetbits_le32(&l2ana_reg->ana_tables.mac_access,
  933. VSC9953_MAC_CMD_MASK |
  934. VSC9953_MAC_ENTRYTYPE_MASK,
  935. VSC9953_MAC_CMD_AGE);
  936. break;
  937. default:
  938. printf("Unknown MAC table command\n");
  939. }
  940. if (vsc9953_mac_table_poll_idle() < 0) {
  941. debug("MAC table timeout\n");
  942. return -1;
  943. }
  944. return 0;
  945. }
  946. /* show the FDB entries that correspond to a port and a VLAN */
  947. static void vsc9953_mac_table_show(int port_no, int vid)
  948. {
  949. int rc[VSC9953_MAX_PORTS];
  950. enum port_learn_mode mode[VSC9953_MAX_PORTS];
  951. int i;
  952. u32 val;
  953. u32 vlan;
  954. u32 mach;
  955. u32 macl;
  956. u32 dest_indx;
  957. struct vsc9953_analyzer *l2ana_reg;
  958. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  959. VSC9953_ANA_OFFSET);
  960. /* disable auto learning */
  961. if (port_no == ETHSW_CMD_PORT_ALL) {
  962. for (i = 0; i < VSC9953_MAX_PORTS; i++) {
  963. rc[i] = vsc9953_port_learn_mode_get(i, &mode[i]);
  964. if (!rc[i] && mode[i] != PORT_LEARN_NONE)
  965. vsc9953_port_learn_mode_set(i, PORT_LEARN_NONE);
  966. }
  967. } else {
  968. rc[port_no] = vsc9953_port_learn_mode_get(port_no,
  969. &mode[port_no]);
  970. if (!rc[port_no] && mode[port_no] != PORT_LEARN_NONE)
  971. vsc9953_port_learn_mode_set(port_no, PORT_LEARN_NONE);
  972. }
  973. /* write port and vid to get selected FDB entries */
  974. val = in_le32(&l2ana_reg->ana.anag_efil);
  975. if (port_no != ETHSW_CMD_PORT_ALL) {
  976. val = bitfield_replace_by_mask(val, VSC9953_AGE_PORT_MASK,
  977. port_no) | VSC9953_AGE_PORT_EN;
  978. }
  979. if (vid != ETHSW_CMD_VLAN_ALL) {
  980. val = bitfield_replace_by_mask(val, VSC9953_AGE_VID_MASK,
  981. vid) | VSC9953_AGE_VID_EN;
  982. }
  983. out_le32(&l2ana_reg->ana.anag_efil, val);
  984. /* set MAC and VLAN to 0 to look from beginning */
  985. clrbits_le32(&l2ana_reg->ana_tables.mach_data,
  986. VSC9953_MAC_VID_MASK | VSC9953_MAC_MACH_MASK);
  987. out_le32(&l2ana_reg->ana_tables.macl_data, 0);
  988. /* get entries */
  989. printf("%10s %17s %5s %4s\n", "EntryType", "MAC", "PORT", "VID");
  990. do {
  991. if (vsc9953_mac_table_cmd(MAC_TABLE_GET_NEXT) < 0) {
  992. debug("GET NEXT MAC table command failed\n");
  993. break;
  994. }
  995. val = in_le32(&l2ana_reg->ana_tables.mac_access);
  996. /* get out when an invalid entry is found */
  997. if (!(val & VSC9953_MAC_CMD_VALID))
  998. break;
  999. switch (val & VSC9953_MAC_ENTRYTYPE_MASK) {
  1000. case VSC9953_MAC_ENTRYTYPE_NORMAL:
  1001. printf("%10s ", "Dynamic");
  1002. break;
  1003. case VSC9953_MAC_ENTRYTYPE_LOCKED:
  1004. printf("%10s ", "Static");
  1005. break;
  1006. case VSC9953_MAC_ENTRYTYPE_IPV4MCAST:
  1007. printf("%10s ", "IPv4 Mcast");
  1008. break;
  1009. case VSC9953_MAC_ENTRYTYPE_IPV6MCAST:
  1010. printf("%10s ", "IPv6 Mcast");
  1011. break;
  1012. default:
  1013. printf("%10s ", "Unknown");
  1014. }
  1015. dest_indx = bitfield_extract_by_mask(val,
  1016. VSC9953_MAC_DESTIDX_MASK);
  1017. val = in_le32(&l2ana_reg->ana_tables.mach_data);
  1018. vlan = bitfield_extract_by_mask(val, VSC9953_MAC_VID_MASK);
  1019. mach = bitfield_extract_by_mask(val, VSC9953_MAC_MACH_MASK);
  1020. macl = in_le32(&l2ana_reg->ana_tables.macl_data);
  1021. printf("%02x:%02x:%02x:%02x:%02x:%02x ", (mach >> 8) & 0xff,
  1022. mach & 0xff, (macl >> 24) & 0xff, (macl >> 16) & 0xff,
  1023. (macl >> 8) & 0xff, macl & 0xff);
  1024. printf("%5d ", dest_indx);
  1025. printf("%4d\n", vlan);
  1026. } while (1);
  1027. /* set learning mode to previous value */
  1028. if (port_no == ETHSW_CMD_PORT_ALL) {
  1029. for (i = 0; i < VSC9953_MAX_PORTS; i++) {
  1030. if (!rc[i] && mode[i] != PORT_LEARN_NONE)
  1031. vsc9953_port_learn_mode_set(i, mode[i]);
  1032. }
  1033. } else {
  1034. /* If administrative down, skip */
  1035. if (!rc[port_no] && mode[port_no] != PORT_LEARN_NONE)
  1036. vsc9953_port_learn_mode_set(port_no, mode[port_no]);
  1037. }
  1038. /* reset FDB port and VLAN FDB selection */
  1039. clrbits_le32(&l2ana_reg->ana.anag_efil, VSC9953_AGE_PORT_EN |
  1040. VSC9953_AGE_PORT_MASK | VSC9953_AGE_VID_EN |
  1041. VSC9953_AGE_VID_MASK);
  1042. }
  1043. /* Add a static FDB entry */
  1044. static int vsc9953_mac_table_add(u8 port_no, uchar mac[6], int vid)
  1045. {
  1046. u32 val;
  1047. struct vsc9953_analyzer *l2ana_reg;
  1048. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  1049. VSC9953_ANA_OFFSET);
  1050. val = in_le32(&l2ana_reg->ana_tables.mach_data);
  1051. val = bitfield_replace_by_mask(val, VSC9953_MACHDATA_VID_MASK, vid) |
  1052. (mac[0] << 8) | (mac[1] << 0);
  1053. out_le32(&l2ana_reg->ana_tables.mach_data, val);
  1054. out_le32(&l2ana_reg->ana_tables.macl_data,
  1055. (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) |
  1056. (mac[5] << 0));
  1057. /* set on which port is the MAC address added */
  1058. val = in_le32(&l2ana_reg->ana_tables.mac_access);
  1059. val = bitfield_replace_by_mask(val, VSC9953_MAC_DESTIDX_MASK, port_no);
  1060. out_le32(&l2ana_reg->ana_tables.mac_access, val);
  1061. if (vsc9953_mac_table_cmd(MAC_TABLE_LEARN) < 0)
  1062. return -1;
  1063. /* check if the MAC address was indeed added */
  1064. val = in_le32(&l2ana_reg->ana_tables.mach_data);
  1065. val = bitfield_replace_by_mask(val, VSC9953_MACHDATA_VID_MASK, vid) |
  1066. (mac[0] << 8) | (mac[1] << 0);
  1067. out_le32(&l2ana_reg->ana_tables.mach_data, val);
  1068. out_le32(&l2ana_reg->ana_tables.macl_data,
  1069. (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) |
  1070. (mac[5] << 0));
  1071. if (vsc9953_mac_table_cmd(MAC_TABLE_READ) < 0)
  1072. return -1;
  1073. val = in_le32(&l2ana_reg->ana_tables.mac_access);
  1074. if ((port_no != bitfield_extract_by_mask(val,
  1075. VSC9953_MAC_DESTIDX_MASK))) {
  1076. printf("Failed to add MAC address\n");
  1077. return -1;
  1078. }
  1079. return 0;
  1080. }
  1081. /* Delete a FDB entry */
  1082. static int vsc9953_mac_table_del(uchar mac[6], u16 vid)
  1083. {
  1084. u32 val;
  1085. struct vsc9953_analyzer *l2ana_reg;
  1086. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  1087. VSC9953_ANA_OFFSET);
  1088. /* check first if MAC entry is present */
  1089. val = in_le32(&l2ana_reg->ana_tables.mach_data);
  1090. val = bitfield_replace_by_mask(val, VSC9953_MACHDATA_VID_MASK, vid) |
  1091. (mac[0] << 8) | (mac[1] << 0);
  1092. out_le32(&l2ana_reg->ana_tables.mach_data, val);
  1093. out_le32(&l2ana_reg->ana_tables.macl_data,
  1094. (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) |
  1095. (mac[5] << 0));
  1096. if (vsc9953_mac_table_cmd(MAC_TABLE_LOOKUP) < 0) {
  1097. debug("Lookup in the MAC table failed\n");
  1098. return -1;
  1099. }
  1100. if (!(in_le32(&l2ana_reg->ana_tables.mac_access) &
  1101. VSC9953_MAC_CMD_VALID)) {
  1102. printf("The MAC address: %02x:%02x:%02x:%02x:%02x:%02x ",
  1103. mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  1104. printf("VLAN: %d does not exist.\n", vid);
  1105. return -1;
  1106. }
  1107. /* FDB entry found, proceed to delete */
  1108. val = in_le32(&l2ana_reg->ana_tables.mach_data);
  1109. val = bitfield_replace_by_mask(val, VSC9953_MACHDATA_VID_MASK, vid) |
  1110. (mac[0] << 8) | (mac[1] << 0);
  1111. out_le32(&l2ana_reg->ana_tables.mach_data, val);
  1112. out_le32(&l2ana_reg->ana_tables.macl_data, (mac[2] << 24) |
  1113. (mac[3] << 16) | (mac[4] << 8) | (mac[5] << 0));
  1114. if (vsc9953_mac_table_cmd(MAC_TABLE_FORGET) < 0)
  1115. return -1;
  1116. /* check if the MAC entry is still in FDB */
  1117. val = in_le32(&l2ana_reg->ana_tables.mach_data);
  1118. val = bitfield_replace_by_mask(val, VSC9953_MACHDATA_VID_MASK, vid) |
  1119. (mac[0] << 8) | (mac[1] << 0);
  1120. out_le32(&l2ana_reg->ana_tables.mach_data, val);
  1121. out_le32(&l2ana_reg->ana_tables.macl_data, (mac[2] << 24) |
  1122. (mac[3] << 16) | (mac[4] << 8) | (mac[5] << 0));
  1123. if (vsc9953_mac_table_cmd(MAC_TABLE_LOOKUP) < 0) {
  1124. debug("Lookup in the MAC table failed\n");
  1125. return -1;
  1126. }
  1127. if (in_le32(&l2ana_reg->ana_tables.mac_access) &
  1128. VSC9953_MAC_CMD_VALID) {
  1129. printf("Failed to delete MAC address\n");
  1130. return -1;
  1131. }
  1132. return 0;
  1133. }
  1134. /* age the unlocked entries in FDB */
  1135. static void vsc9953_mac_table_age(int port_no, int vid)
  1136. {
  1137. int rc[VSC9953_MAX_PORTS];
  1138. enum port_learn_mode mode[VSC9953_MAX_PORTS];
  1139. u32 val;
  1140. int i;
  1141. struct vsc9953_analyzer *l2ana_reg;
  1142. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  1143. VSC9953_ANA_OFFSET);
  1144. /* set port and VID for selective aging */
  1145. val = in_le32(&l2ana_reg->ana.anag_efil);
  1146. if (port_no != ETHSW_CMD_PORT_ALL) {
  1147. /* disable auto learning */
  1148. rc[port_no] = vsc9953_port_learn_mode_get(port_no,
  1149. &mode[port_no]);
  1150. if (!rc[port_no] && mode[port_no] != PORT_LEARN_NONE)
  1151. vsc9953_port_learn_mode_set(port_no, PORT_LEARN_NONE);
  1152. val = bitfield_replace_by_mask(val, VSC9953_AGE_PORT_MASK,
  1153. port_no) | VSC9953_AGE_PORT_EN;
  1154. } else {
  1155. /* disable auto learning on all ports */
  1156. for (i = 0; i < VSC9953_MAX_PORTS; i++) {
  1157. rc[i] = vsc9953_port_learn_mode_get(i, &mode[i]);
  1158. if (!rc[i] && mode[i] != PORT_LEARN_NONE)
  1159. vsc9953_port_learn_mode_set(i, PORT_LEARN_NONE);
  1160. }
  1161. }
  1162. if (vid != ETHSW_CMD_VLAN_ALL) {
  1163. val = bitfield_replace_by_mask(val, VSC9953_AGE_VID_MASK, vid) |
  1164. VSC9953_AGE_VID_EN;
  1165. }
  1166. out_le32(&l2ana_reg->ana.anag_efil, val);
  1167. /* age the dynamic FDB entries */
  1168. vsc9953_mac_table_cmd(MAC_TABLE_AGE);
  1169. /* clear previously set port and VID */
  1170. clrbits_le32(&l2ana_reg->ana.anag_efil, VSC9953_AGE_PORT_EN |
  1171. VSC9953_AGE_PORT_MASK | VSC9953_AGE_VID_EN |
  1172. VSC9953_AGE_VID_MASK);
  1173. if (port_no != ETHSW_CMD_PORT_ALL) {
  1174. if (!rc[port_no] && mode[port_no] != PORT_LEARN_NONE)
  1175. vsc9953_port_learn_mode_set(port_no, mode[port_no]);
  1176. } else {
  1177. for (i = 0; i < VSC9953_MAX_PORTS; i++) {
  1178. if (!rc[i] && mode[i] != PORT_LEARN_NONE)
  1179. vsc9953_port_learn_mode_set(i, mode[i]);
  1180. }
  1181. }
  1182. }
  1183. /* Delete all the dynamic FDB entries */
  1184. static void vsc9953_mac_table_flush(int port, int vid)
  1185. {
  1186. vsc9953_mac_table_age(port, vid);
  1187. vsc9953_mac_table_age(port, vid);
  1188. }
  1189. enum egress_vlan_tag {
  1190. EGR_TAG_CLASS = 0,
  1191. EGR_TAG_PVID,
  1192. };
  1193. /* Set egress tag mode for a VSC9953 port */
  1194. static void vsc9953_port_vlan_egress_tag_set(int port_no,
  1195. enum egress_vlan_tag mode)
  1196. {
  1197. struct vsc9953_rew_reg *l2rew_reg;
  1198. l2rew_reg = (struct vsc9953_rew_reg *)(VSC9953_OFFSET +
  1199. VSC9953_REW_OFFSET);
  1200. switch (mode) {
  1201. case EGR_TAG_CLASS:
  1202. clrbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
  1203. VSC9953_TAG_VID_PVID);
  1204. break;
  1205. case EGR_TAG_PVID:
  1206. setbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
  1207. VSC9953_TAG_VID_PVID);
  1208. break;
  1209. default:
  1210. printf("Unknown egress VLAN tag mode for port %d\n", port_no);
  1211. }
  1212. }
  1213. /* Get egress tag mode for a VSC9953 port */
  1214. static void vsc9953_port_vlan_egress_tag_get(int port_no,
  1215. enum egress_vlan_tag *mode)
  1216. {
  1217. u32 val;
  1218. struct vsc9953_rew_reg *l2rew_reg;
  1219. l2rew_reg = (struct vsc9953_rew_reg *)(VSC9953_OFFSET +
  1220. VSC9953_REW_OFFSET);
  1221. val = in_le32(&l2rew_reg->port[port_no].port_tag_cfg);
  1222. if (val & VSC9953_TAG_VID_PVID)
  1223. *mode = EGR_TAG_PVID;
  1224. else
  1225. *mode = EGR_TAG_CLASS;
  1226. }
  1227. /* VSC9953 VLAN learning modes */
  1228. enum vlan_learning_mode {
  1229. SHARED_VLAN_LEARNING,
  1230. PRIVATE_VLAN_LEARNING,
  1231. };
  1232. /* Set VLAN learning mode for VSC9953 */
  1233. static void vsc9953_vlan_learning_set(enum vlan_learning_mode lrn_mode)
  1234. {
  1235. struct vsc9953_analyzer *l2ana_reg;
  1236. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  1237. VSC9953_ANA_OFFSET);
  1238. switch (lrn_mode) {
  1239. case SHARED_VLAN_LEARNING:
  1240. setbits_le32(&l2ana_reg->ana.agen_ctrl, VSC9953_FID_MASK_ALL);
  1241. break;
  1242. case PRIVATE_VLAN_LEARNING:
  1243. clrbits_le32(&l2ana_reg->ana.agen_ctrl, VSC9953_FID_MASK_ALL);
  1244. break;
  1245. default:
  1246. printf("Unknown VLAN learn mode\n");
  1247. }
  1248. }
  1249. /* Get VLAN learning mode for VSC9953 */
  1250. static int vsc9953_vlan_learning_get(enum vlan_learning_mode *lrn_mode)
  1251. {
  1252. u32 val;
  1253. struct vsc9953_analyzer *l2ana_reg;
  1254. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  1255. VSC9953_ANA_OFFSET);
  1256. val = in_le32(&l2ana_reg->ana.agen_ctrl);
  1257. if (!(val & VSC9953_FID_MASK_ALL)) {
  1258. *lrn_mode = PRIVATE_VLAN_LEARNING;
  1259. } else if ((val & VSC9953_FID_MASK_ALL) == VSC9953_FID_MASK_ALL) {
  1260. *lrn_mode = SHARED_VLAN_LEARNING;
  1261. } else {
  1262. printf("Unknown VLAN learning mode\n");
  1263. return -EINVAL;
  1264. }
  1265. return 0;
  1266. }
  1267. /* Enable/disable VLAN ingress filtering on a VSC9953 port */
  1268. static void vsc9953_port_ingress_filtering_set(int port_no, int enabled)
  1269. {
  1270. struct vsc9953_analyzer *l2ana_reg;
  1271. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  1272. VSC9953_ANA_OFFSET);
  1273. if (enabled)
  1274. setbits_le32(&l2ana_reg->ana.vlan_mask, 1 << port_no);
  1275. else
  1276. clrbits_le32(&l2ana_reg->ana.vlan_mask, 1 << port_no);
  1277. }
  1278. /* Return VLAN ingress filtering on a VSC9953 port */
  1279. static int vsc9953_port_ingress_filtering_get(int port_no)
  1280. {
  1281. u32 val;
  1282. struct vsc9953_analyzer *l2ana_reg;
  1283. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  1284. VSC9953_ANA_OFFSET);
  1285. val = in_le32(&l2ana_reg->ana.vlan_mask);
  1286. return !!(val & (1 << port_no));
  1287. }
  1288. /* Get the aggregation group of a port */
  1289. static int vsc9953_port_aggr_grp_get(int port_no, int *aggr_grp)
  1290. {
  1291. u32 val;
  1292. struct vsc9953_analyzer *l2ana_reg;
  1293. if (!VSC9953_PORT_CHECK(port_no))
  1294. return -EINVAL;
  1295. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  1296. VSC9953_ANA_OFFSET);
  1297. val = in_le32(&l2ana_reg->port[port_no].port_cfg);
  1298. *aggr_grp = bitfield_extract_by_mask(val,
  1299. VSC9953_PORT_CFG_PORTID_MASK);
  1300. return 0;
  1301. }
  1302. static void vsc9953_aggr_grp_members_get(int aggr_grp,
  1303. u8 aggr_membr[VSC9953_MAX_PORTS])
  1304. {
  1305. int port_no;
  1306. int aggr_membr_grp;
  1307. for (port_no = 0; port_no < VSC9953_MAX_PORTS; port_no++) {
  1308. aggr_membr[port_no] = 0;
  1309. if (vsc9953_port_aggr_grp_get(port_no, &aggr_membr_grp))
  1310. continue;
  1311. if (aggr_grp == aggr_membr_grp)
  1312. aggr_membr[port_no] = 1;
  1313. }
  1314. }
  1315. static void vsc9953_update_dest_members_masks(int port_no, u32 membr_bitfld_old,
  1316. u32 membr_bitfld_new)
  1317. {
  1318. int i;
  1319. u32 pgid;
  1320. struct vsc9953_analyzer *l2ana_reg;
  1321. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  1322. VSC9953_ANA_OFFSET);
  1323. /*
  1324. * NOTE: Only the unicast destination masks are updated, since
  1325. * we do not support for now Layer-2 multicast entries
  1326. */
  1327. for (i = 0; i < VSC9953_MAX_PORTS; i++) {
  1328. if (i == port_no) {
  1329. clrsetbits_le32(&l2ana_reg->port_id_tbl.port_grp_id[i],
  1330. VSC9953_PGID_PORT_MASK,
  1331. membr_bitfld_new);
  1332. continue;
  1333. }
  1334. pgid = in_le32(&l2ana_reg->port_id_tbl.port_grp_id[i]);
  1335. if ((u32)(1 << i) & membr_bitfld_old & VSC9953_PGID_PORT_MASK)
  1336. pgid &= ~((u32)(1 << port_no));
  1337. if ((u32)(1 << i) & membr_bitfld_new & VSC9953_PGID_PORT_MASK)
  1338. pgid |= ((u32)(1 << port_no));
  1339. out_le32(&l2ana_reg->port_id_tbl.port_grp_id[i], pgid);
  1340. }
  1341. }
  1342. static void vsc9953_update_source_members_masks(int port_no,
  1343. u32 membr_bitfld_old,
  1344. u32 membr_bitfld_new)
  1345. {
  1346. int i;
  1347. int index;
  1348. u32 pgid;
  1349. struct vsc9953_analyzer *l2ana_reg;
  1350. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  1351. VSC9953_ANA_OFFSET);
  1352. for (i = 0; i < VSC9953_MAX_PORTS + 1; i++) {
  1353. index = PGID_SRC_START + i;
  1354. pgid = in_le32(&l2ana_reg->port_id_tbl.port_grp_id[index]);
  1355. if (i == port_no) {
  1356. pgid = (pgid | VSC9953_PGID_PORT_MASK) &
  1357. ~membr_bitfld_new;
  1358. out_le32(&l2ana_reg->port_id_tbl.port_grp_id[index],
  1359. pgid);
  1360. continue;
  1361. }
  1362. if ((u32)(1 << i) & membr_bitfld_old & VSC9953_PGID_PORT_MASK)
  1363. pgid |= (u32)(1 << port_no);
  1364. if ((u32)(1 << i) & membr_bitfld_new & VSC9953_PGID_PORT_MASK)
  1365. pgid &= ~(u32)(1 << port_no);
  1366. out_le32(&l2ana_reg->port_id_tbl.port_grp_id[index], pgid);
  1367. }
  1368. }
  1369. static u32 vsc9953_aggr_mask_get_next(u32 aggr_mask, u32 member_bitfield)
  1370. {
  1371. if (!member_bitfield)
  1372. return 0;
  1373. if (!(aggr_mask & VSC9953_PGID_PORT_MASK))
  1374. aggr_mask = 1;
  1375. else
  1376. aggr_mask <<= 1;
  1377. while (!(aggr_mask & member_bitfield)) {
  1378. aggr_mask <<= 1;
  1379. if (!(aggr_mask & VSC9953_PGID_PORT_MASK))
  1380. aggr_mask = 1;
  1381. }
  1382. return aggr_mask;
  1383. }
  1384. static void vsc9953_update_aggr_members_masks(int port_no, u32 membr_bitfld_old,
  1385. u32 membr_bitfld_new)
  1386. {
  1387. int i;
  1388. u32 pgid;
  1389. u32 aggr_mask_old = 0;
  1390. u32 aggr_mask_new = 0;
  1391. struct vsc9953_analyzer *l2ana_reg;
  1392. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  1393. VSC9953_ANA_OFFSET);
  1394. /* Update all the PGID aggregation masks */
  1395. for (i = PGID_AGGR_START; i < PGID_SRC_START; i++) {
  1396. pgid = in_le32(&l2ana_reg->port_id_tbl.port_grp_id[i]);
  1397. aggr_mask_old = vsc9953_aggr_mask_get_next(aggr_mask_old,
  1398. membr_bitfld_old);
  1399. pgid = (pgid & ~membr_bitfld_old) | aggr_mask_old;
  1400. aggr_mask_new = vsc9953_aggr_mask_get_next(aggr_mask_new,
  1401. membr_bitfld_new);
  1402. pgid = (pgid & ~membr_bitfld_new) | aggr_mask_new;
  1403. out_le32(&l2ana_reg->port_id_tbl.port_grp_id[i], pgid);
  1404. }
  1405. }
  1406. static u32 vsc9953_aggr_membr_bitfield_get(u8 member[VSC9953_MAX_PORTS])
  1407. {
  1408. int i;
  1409. u32 member_bitfield = 0;
  1410. for (i = 0; i < VSC9953_MAX_PORTS; i++) {
  1411. if (member[i])
  1412. member_bitfield |= 1 << i;
  1413. }
  1414. member_bitfield &= VSC9953_PGID_PORT_MASK;
  1415. return member_bitfield;
  1416. }
  1417. static void vsc9953_update_members_masks(int port_no,
  1418. u8 member_old[VSC9953_MAX_PORTS],
  1419. u8 member_new[VSC9953_MAX_PORTS])
  1420. {
  1421. u32 membr_bitfld_old = vsc9953_aggr_membr_bitfield_get(member_old);
  1422. u32 membr_bitfld_new = vsc9953_aggr_membr_bitfield_get(member_new);
  1423. vsc9953_update_dest_members_masks(port_no, membr_bitfld_old,
  1424. membr_bitfld_new);
  1425. vsc9953_update_source_members_masks(port_no, membr_bitfld_old,
  1426. membr_bitfld_new);
  1427. vsc9953_update_aggr_members_masks(port_no, membr_bitfld_old,
  1428. membr_bitfld_new);
  1429. }
  1430. /* Set the aggregation group of a port */
  1431. static int vsc9953_port_aggr_grp_set(int port_no, int aggr_grp)
  1432. {
  1433. u8 aggr_membr_old[VSC9953_MAX_PORTS];
  1434. u8 aggr_membr_new[VSC9953_MAX_PORTS];
  1435. int rc;
  1436. int aggr_grp_old;
  1437. u32 val;
  1438. struct vsc9953_analyzer *l2ana_reg;
  1439. if (!VSC9953_PORT_CHECK(port_no) || !VSC9953_PORT_CHECK(aggr_grp))
  1440. return -EINVAL;
  1441. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  1442. VSC9953_ANA_OFFSET);
  1443. rc = vsc9953_port_aggr_grp_get(port_no, &aggr_grp_old);
  1444. if (rc)
  1445. return rc;
  1446. /* get all the members of the old aggregation group */
  1447. vsc9953_aggr_grp_members_get(aggr_grp_old, aggr_membr_old);
  1448. /* get all the members of the same aggregation group */
  1449. vsc9953_aggr_grp_members_get(aggr_grp, aggr_membr_new);
  1450. /* add current port as member to the new aggregation group */
  1451. aggr_membr_old[port_no] = 0;
  1452. aggr_membr_new[port_no] = 1;
  1453. /* update masks */
  1454. vsc9953_update_members_masks(port_no, aggr_membr_old, aggr_membr_new);
  1455. /* Change logical port number */
  1456. val = in_le32(&l2ana_reg->port[port_no].port_cfg);
  1457. val = bitfield_replace_by_mask(val,
  1458. VSC9953_PORT_CFG_PORTID_MASK, aggr_grp);
  1459. out_le32(&l2ana_reg->port[port_no].port_cfg, val);
  1460. return 0;
  1461. }
  1462. static int vsc9953_port_status_key_func(struct ethsw_command_def *parsed_cmd)
  1463. {
  1464. int i;
  1465. u8 enabled;
  1466. /* Last keyword should tell us if we should enable/disable the port */
  1467. if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
  1468. ethsw_id_enable)
  1469. enabled = 1;
  1470. else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
  1471. ethsw_id_disable)
  1472. enabled = 0;
  1473. else
  1474. return CMD_RET_USAGE;
  1475. if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
  1476. if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
  1477. printf("Invalid port number: %d\n", parsed_cmd->port);
  1478. return CMD_RET_FAILURE;
  1479. }
  1480. vsc9953_port_status_set(parsed_cmd->port, enabled);
  1481. } else {
  1482. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  1483. vsc9953_port_status_set(i, enabled);
  1484. }
  1485. return CMD_RET_SUCCESS;
  1486. }
  1487. static int vsc9953_port_config_key_func(struct ethsw_command_def *parsed_cmd)
  1488. {
  1489. int i;
  1490. if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
  1491. if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
  1492. printf("Invalid port number: %d\n", parsed_cmd->port);
  1493. return CMD_RET_FAILURE;
  1494. }
  1495. vsc9953_phy_autoneg(parsed_cmd->port);
  1496. printf("%8s %8s %8s %8s %8s\n",
  1497. "Port", "Status", "Link", "Speed",
  1498. "Duplex");
  1499. vsc9953_port_config_show(parsed_cmd->port);
  1500. } else {
  1501. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  1502. vsc9953_phy_autoneg(i);
  1503. printf("%8s %8s %8s %8s %8s\n",
  1504. "Port", "Status", "Link", "Speed", "Duplex");
  1505. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  1506. vsc9953_port_config_show(i);
  1507. }
  1508. return CMD_RET_SUCCESS;
  1509. }
  1510. static int vsc9953_port_stats_key_func(struct ethsw_command_def *parsed_cmd)
  1511. {
  1512. int i;
  1513. if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
  1514. if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
  1515. printf("Invalid port number: %d\n", parsed_cmd->port);
  1516. return CMD_RET_FAILURE;
  1517. }
  1518. vsc9953_port_statistics_show(parsed_cmd->port);
  1519. } else {
  1520. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  1521. vsc9953_port_statistics_show(i);
  1522. }
  1523. return CMD_RET_SUCCESS;
  1524. }
  1525. static int vsc9953_port_stats_clear_key_func(struct ethsw_command_def
  1526. *parsed_cmd)
  1527. {
  1528. int i;
  1529. if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
  1530. if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
  1531. printf("Invalid port number: %d\n", parsed_cmd->port);
  1532. return CMD_RET_FAILURE;
  1533. }
  1534. vsc9953_port_statistics_clear(parsed_cmd->port);
  1535. } else {
  1536. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  1537. vsc9953_port_statistics_clear(i);
  1538. }
  1539. return CMD_RET_SUCCESS;
  1540. }
  1541. static int vsc9953_learn_show_key_func(struct ethsw_command_def *parsed_cmd)
  1542. {
  1543. int i;
  1544. enum port_learn_mode mode;
  1545. if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
  1546. if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
  1547. printf("Invalid port number: %d\n", parsed_cmd->port);
  1548. return CMD_RET_FAILURE;
  1549. }
  1550. if (vsc9953_port_learn_mode_get(parsed_cmd->port, &mode))
  1551. return CMD_RET_FAILURE;
  1552. printf("%7s %11s\n", "Port", "Learn mode");
  1553. switch (mode) {
  1554. case PORT_LEARN_NONE:
  1555. printf("%7d %11s\n", parsed_cmd->port, "disable");
  1556. break;
  1557. case PORT_LEARN_AUTO:
  1558. printf("%7d %11s\n", parsed_cmd->port, "auto");
  1559. break;
  1560. default:
  1561. printf("%7d %11s\n", parsed_cmd->port, "-");
  1562. }
  1563. } else {
  1564. printf("%7s %11s\n", "Port", "Learn mode");
  1565. for (i = 0; i < VSC9953_MAX_PORTS; i++) {
  1566. if (vsc9953_port_learn_mode_get(i, &mode))
  1567. continue;
  1568. switch (mode) {
  1569. case PORT_LEARN_NONE:
  1570. printf("%7d %11s\n", i, "disable");
  1571. break;
  1572. case PORT_LEARN_AUTO:
  1573. printf("%7d %11s\n", i, "auto");
  1574. break;
  1575. default:
  1576. printf("%7d %11s\n", i, "-");
  1577. }
  1578. }
  1579. }
  1580. return CMD_RET_SUCCESS;
  1581. }
  1582. static int vsc9953_learn_set_key_func(struct ethsw_command_def *parsed_cmd)
  1583. {
  1584. int i;
  1585. enum port_learn_mode mode;
  1586. /* Last keyword should tell us the learn mode */
  1587. if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
  1588. ethsw_id_auto)
  1589. mode = PORT_LEARN_AUTO;
  1590. else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
  1591. ethsw_id_disable)
  1592. mode = PORT_LEARN_NONE;
  1593. else
  1594. return CMD_RET_USAGE;
  1595. if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
  1596. if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
  1597. printf("Invalid port number: %d\n", parsed_cmd->port);
  1598. return CMD_RET_FAILURE;
  1599. }
  1600. vsc9953_port_learn_mode_set(parsed_cmd->port, mode);
  1601. } else {
  1602. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  1603. vsc9953_port_learn_mode_set(i, mode);
  1604. }
  1605. return CMD_RET_SUCCESS;
  1606. }
  1607. static int vsc9953_fdb_show_key_func(struct ethsw_command_def *parsed_cmd)
  1608. {
  1609. if (parsed_cmd->port != ETHSW_CMD_PORT_ALL &&
  1610. !VSC9953_PORT_CHECK(parsed_cmd->port)) {
  1611. printf("Invalid port number: %d\n", parsed_cmd->port);
  1612. return CMD_RET_FAILURE;
  1613. }
  1614. if (parsed_cmd->vid != ETHSW_CMD_VLAN_ALL &&
  1615. !VSC9953_VLAN_CHECK(parsed_cmd->vid)) {
  1616. printf("Invalid VID number: %d\n", parsed_cmd->vid);
  1617. return CMD_RET_FAILURE;
  1618. }
  1619. vsc9953_mac_table_show(parsed_cmd->port, parsed_cmd->vid);
  1620. return CMD_RET_SUCCESS;
  1621. }
  1622. static int vsc9953_fdb_flush_key_func(struct ethsw_command_def *parsed_cmd)
  1623. {
  1624. if (parsed_cmd->port != ETHSW_CMD_PORT_ALL &&
  1625. !VSC9953_PORT_CHECK(parsed_cmd->port)) {
  1626. printf("Invalid port number: %d\n", parsed_cmd->port);
  1627. return CMD_RET_FAILURE;
  1628. }
  1629. if (parsed_cmd->vid != ETHSW_CMD_VLAN_ALL &&
  1630. !VSC9953_VLAN_CHECK(parsed_cmd->vid)) {
  1631. printf("Invalid VID number: %d\n", parsed_cmd->vid);
  1632. return CMD_RET_FAILURE;
  1633. }
  1634. vsc9953_mac_table_flush(parsed_cmd->port, parsed_cmd->vid);
  1635. return CMD_RET_SUCCESS;
  1636. }
  1637. static int vsc9953_fdb_entry_add_key_func(struct ethsw_command_def *parsed_cmd)
  1638. {
  1639. int vid;
  1640. /* a port number must be present */
  1641. if (parsed_cmd->port == ETHSW_CMD_PORT_ALL) {
  1642. printf("Please specify a port\n");
  1643. return CMD_RET_FAILURE;
  1644. }
  1645. if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
  1646. printf("Invalid port number: %d\n", parsed_cmd->port);
  1647. return CMD_RET_FAILURE;
  1648. }
  1649. /* Use VLAN 1 if VID is not set */
  1650. vid = (parsed_cmd->vid == ETHSW_CMD_VLAN_ALL ? 1 : parsed_cmd->vid);
  1651. if (!VSC9953_VLAN_CHECK(vid)) {
  1652. printf("Invalid VID number: %d\n", vid);
  1653. return CMD_RET_FAILURE;
  1654. }
  1655. if (vsc9953_mac_table_add(parsed_cmd->port, parsed_cmd->ethaddr, vid))
  1656. return CMD_RET_FAILURE;
  1657. return CMD_RET_SUCCESS;
  1658. }
  1659. static int vsc9953_fdb_entry_del_key_func(struct ethsw_command_def *parsed_cmd)
  1660. {
  1661. int vid;
  1662. /* Use VLAN 1 if VID is not set */
  1663. vid = (parsed_cmd->vid == ETHSW_CMD_VLAN_ALL ? 1 : parsed_cmd->vid);
  1664. if (!VSC9953_VLAN_CHECK(vid)) {
  1665. printf("Invalid VID number: %d\n", vid);
  1666. return CMD_RET_FAILURE;
  1667. }
  1668. if (vsc9953_mac_table_del(parsed_cmd->ethaddr, vid))
  1669. return CMD_RET_FAILURE;
  1670. return CMD_RET_SUCCESS;
  1671. }
  1672. static int vsc9953_pvid_show_key_func(struct ethsw_command_def *parsed_cmd)
  1673. {
  1674. int i;
  1675. int pvid;
  1676. if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
  1677. if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
  1678. printf("Invalid port number: %d\n", parsed_cmd->port);
  1679. return CMD_RET_FAILURE;
  1680. }
  1681. if (vsc9953_port_vlan_pvid_get(parsed_cmd->port, &pvid))
  1682. return CMD_RET_FAILURE;
  1683. printf("%7s %7s\n", "Port", "PVID");
  1684. printf("%7d %7d\n", parsed_cmd->port, pvid);
  1685. } else {
  1686. printf("%7s %7s\n", "Port", "PVID");
  1687. for (i = 0; i < VSC9953_MAX_PORTS; i++) {
  1688. if (vsc9953_port_vlan_pvid_get(i, &pvid))
  1689. continue;
  1690. printf("%7d %7d\n", i, pvid);
  1691. }
  1692. }
  1693. return CMD_RET_SUCCESS;
  1694. }
  1695. static int vsc9953_pvid_set_key_func(struct ethsw_command_def *parsed_cmd)
  1696. {
  1697. /* PVID number should be set in parsed_cmd->vid */
  1698. if (parsed_cmd->vid == ETHSW_CMD_VLAN_ALL) {
  1699. printf("Please set a pvid value\n");
  1700. return CMD_RET_FAILURE;
  1701. }
  1702. if (!VSC9953_VLAN_CHECK(parsed_cmd->vid)) {
  1703. printf("Invalid VID number: %d\n", parsed_cmd->vid);
  1704. return CMD_RET_FAILURE;
  1705. }
  1706. if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
  1707. if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
  1708. printf("Invalid port number: %d\n", parsed_cmd->port);
  1709. return CMD_RET_FAILURE;
  1710. }
  1711. vsc9953_port_vlan_pvid_set(parsed_cmd->port, parsed_cmd->vid);
  1712. } else {
  1713. vsc9953_port_all_vlan_pvid_set(parsed_cmd->vid);
  1714. }
  1715. return CMD_RET_SUCCESS;
  1716. }
  1717. static int vsc9953_vlan_show_key_func(struct ethsw_command_def *parsed_cmd)
  1718. {
  1719. int i;
  1720. if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
  1721. if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
  1722. printf("Invalid port number: %d\n", parsed_cmd->port);
  1723. return CMD_RET_FAILURE;
  1724. }
  1725. vsc9953_vlan_membership_show(parsed_cmd->port);
  1726. } else {
  1727. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  1728. vsc9953_vlan_membership_show(i);
  1729. }
  1730. return CMD_RET_SUCCESS;
  1731. }
  1732. static int vsc9953_vlan_set_key_func(struct ethsw_command_def *parsed_cmd)
  1733. {
  1734. int i;
  1735. int add;
  1736. /* VLAN should be set in parsed_cmd->vid */
  1737. if (parsed_cmd->vid == ETHSW_CMD_VLAN_ALL) {
  1738. printf("Please set a vlan value\n");
  1739. return CMD_RET_FAILURE;
  1740. }
  1741. if (!VSC9953_VLAN_CHECK(parsed_cmd->vid)) {
  1742. printf("Invalid VID number: %d\n", parsed_cmd->vid);
  1743. return CMD_RET_FAILURE;
  1744. }
  1745. /* keywords add/delete should be the last but one in array */
  1746. if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 2] ==
  1747. ethsw_id_add)
  1748. add = 1;
  1749. else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 2] ==
  1750. ethsw_id_del)
  1751. add = 0;
  1752. else
  1753. return CMD_RET_USAGE;
  1754. if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
  1755. if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
  1756. printf("Invalid port number: %d\n", parsed_cmd->port);
  1757. return CMD_RET_FAILURE;
  1758. }
  1759. vsc9953_vlan_table_membership_set(parsed_cmd->vid,
  1760. parsed_cmd->port, add);
  1761. } else {
  1762. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  1763. vsc9953_vlan_table_membership_set(parsed_cmd->vid, i,
  1764. add);
  1765. }
  1766. return CMD_RET_SUCCESS;
  1767. }
  1768. static int vsc9953_port_untag_show_key_func(
  1769. struct ethsw_command_def *parsed_cmd)
  1770. {
  1771. int i;
  1772. printf("%7s\t%17s\n", "Port", "Untag");
  1773. if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
  1774. if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
  1775. printf("Invalid port number: %d\n", parsed_cmd->port);
  1776. return CMD_RET_FAILURE;
  1777. }
  1778. vsc9953_port_vlan_egr_untag_show(parsed_cmd->port);
  1779. } else {
  1780. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  1781. vsc9953_port_vlan_egr_untag_show(i);
  1782. }
  1783. return CMD_RET_SUCCESS;
  1784. }
  1785. static int vsc9953_port_untag_set_key_func(struct ethsw_command_def *parsed_cmd)
  1786. {
  1787. int i;
  1788. enum egress_untag_mode mode;
  1789. /* keywords for the untagged mode are the last in the array */
  1790. if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
  1791. ethsw_id_all)
  1792. mode = EGRESS_UNTAG_ALL;
  1793. else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
  1794. ethsw_id_none)
  1795. mode = EGRESS_UNTAG_NONE;
  1796. else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
  1797. ethsw_id_pvid)
  1798. mode = EGRESS_UNTAG_PVID_AND_ZERO;
  1799. else
  1800. return CMD_RET_USAGE;
  1801. if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
  1802. if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
  1803. printf("Invalid port number: %d\n", parsed_cmd->port);
  1804. return CMD_RET_FAILURE;
  1805. }
  1806. vsc9953_port_vlan_egr_untag_set(parsed_cmd->port, mode);
  1807. } else {
  1808. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  1809. vsc9953_port_vlan_egr_untag_set(i, mode);
  1810. }
  1811. return CMD_RET_SUCCESS;
  1812. }
  1813. static int vsc9953_egr_vlan_tag_show_key_func(
  1814. struct ethsw_command_def *parsed_cmd)
  1815. {
  1816. int i;
  1817. enum egress_vlan_tag mode;
  1818. if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
  1819. if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
  1820. printf("Invalid port number: %d\n", parsed_cmd->port);
  1821. return CMD_RET_FAILURE;
  1822. }
  1823. vsc9953_port_vlan_egress_tag_get(parsed_cmd->port, &mode);
  1824. printf("%7s\t%12s\n", "Port", "Egress VID");
  1825. printf("%7d\t", parsed_cmd->port);
  1826. switch (mode) {
  1827. case EGR_TAG_CLASS:
  1828. printf("%12s\n", "classified");
  1829. break;
  1830. case EGR_TAG_PVID:
  1831. printf("%12s\n", "pvid");
  1832. break;
  1833. default:
  1834. printf("%12s\n", "-");
  1835. }
  1836. } else {
  1837. printf("%7s\t%12s\n", "Port", "Egress VID");
  1838. for (i = 0; i < VSC9953_MAX_PORTS; i++) {
  1839. vsc9953_port_vlan_egress_tag_get(i, &mode);
  1840. switch (mode) {
  1841. case EGR_TAG_CLASS:
  1842. printf("%7d\t%12s\n", i, "classified");
  1843. break;
  1844. case EGR_TAG_PVID:
  1845. printf("%7d\t%12s\n", i, "pvid");
  1846. break;
  1847. default:
  1848. printf("%7d\t%12s\n", i, "-");
  1849. }
  1850. }
  1851. }
  1852. return CMD_RET_SUCCESS;
  1853. }
  1854. static int vsc9953_egr_vlan_tag_set_key_func(
  1855. struct ethsw_command_def *parsed_cmd)
  1856. {
  1857. int i;
  1858. enum egress_vlan_tag mode;
  1859. /* keywords for the egress vlan tag mode are the last in the array */
  1860. if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
  1861. ethsw_id_pvid)
  1862. mode = EGR_TAG_PVID;
  1863. else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
  1864. ethsw_id_classified)
  1865. mode = EGR_TAG_CLASS;
  1866. else
  1867. return CMD_RET_USAGE;
  1868. if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
  1869. if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
  1870. printf("Invalid port number: %d\n", parsed_cmd->port);
  1871. return CMD_RET_FAILURE;
  1872. }
  1873. vsc9953_port_vlan_egress_tag_set(parsed_cmd->port, mode);
  1874. } else {
  1875. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  1876. vsc9953_port_vlan_egress_tag_set(i, mode);
  1877. }
  1878. return CMD_RET_SUCCESS;
  1879. }
  1880. static int vsc9953_vlan_learn_show_key_func(
  1881. struct ethsw_command_def *parsed_cmd)
  1882. {
  1883. int rc;
  1884. enum vlan_learning_mode mode;
  1885. rc = vsc9953_vlan_learning_get(&mode);
  1886. if (rc)
  1887. return CMD_RET_FAILURE;
  1888. switch (mode) {
  1889. case SHARED_VLAN_LEARNING:
  1890. printf("VLAN learning mode: shared\n");
  1891. break;
  1892. case PRIVATE_VLAN_LEARNING:
  1893. printf("VLAN learning mode: private\n");
  1894. break;
  1895. default:
  1896. printf("Unknown VLAN learning mode\n");
  1897. rc = CMD_RET_FAILURE;
  1898. }
  1899. return CMD_RET_SUCCESS;
  1900. }
  1901. static int vsc9953_vlan_learn_set_key_func(struct ethsw_command_def *parsed_cmd)
  1902. {
  1903. enum vlan_learning_mode mode;
  1904. /* keywords for shared/private are the last in the array */
  1905. if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
  1906. ethsw_id_shared)
  1907. mode = SHARED_VLAN_LEARNING;
  1908. else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
  1909. ethsw_id_private)
  1910. mode = PRIVATE_VLAN_LEARNING;
  1911. else
  1912. return CMD_RET_USAGE;
  1913. vsc9953_vlan_learning_set(mode);
  1914. return CMD_RET_SUCCESS;
  1915. }
  1916. static int vsc9953_ingr_fltr_show_key_func(struct ethsw_command_def *parsed_cmd)
  1917. {
  1918. int i;
  1919. int enabled;
  1920. printf("%7s\t%18s\n", "Port", "Ingress filtering");
  1921. if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
  1922. if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
  1923. printf("Invalid port number: %d\n", parsed_cmd->port);
  1924. return CMD_RET_FAILURE;
  1925. }
  1926. enabled = vsc9953_port_ingress_filtering_get(parsed_cmd->port);
  1927. printf("%7d\t%18s\n", parsed_cmd->port, enabled ? "enable" :
  1928. "disable");
  1929. } else {
  1930. for (i = 0; i < VSC9953_MAX_PORTS; i++) {
  1931. enabled = vsc9953_port_ingress_filtering_get(i);
  1932. printf("%7d\t%18s\n", parsed_cmd->port, enabled ?
  1933. "enable" :
  1934. "disable");
  1935. }
  1936. }
  1937. return CMD_RET_SUCCESS;
  1938. }
  1939. static int vsc9953_ingr_fltr_set_key_func(struct ethsw_command_def *parsed_cmd)
  1940. {
  1941. int i;
  1942. int enable;
  1943. /* keywords for enabling/disabling ingress filtering
  1944. * are the last in the array
  1945. */
  1946. if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
  1947. ethsw_id_enable)
  1948. enable = 1;
  1949. else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
  1950. ethsw_id_disable)
  1951. enable = 0;
  1952. else
  1953. return CMD_RET_USAGE;
  1954. if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
  1955. if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
  1956. printf("Invalid port number: %d\n", parsed_cmd->port);
  1957. return CMD_RET_FAILURE;
  1958. }
  1959. vsc9953_port_ingress_filtering_set(parsed_cmd->port, enable);
  1960. } else {
  1961. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  1962. vsc9953_port_ingress_filtering_set(i, enable);
  1963. }
  1964. return CMD_RET_SUCCESS;
  1965. }
  1966. static int vsc9953_port_aggr_show_key_func(struct ethsw_command_def *parsed_cmd)
  1967. {
  1968. int i;
  1969. int aggr_grp;
  1970. if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
  1971. if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
  1972. printf("Invalid port number: %d\n", parsed_cmd->port);
  1973. return CMD_RET_FAILURE;
  1974. }
  1975. if (vsc9953_port_aggr_grp_get(parsed_cmd->port, &aggr_grp))
  1976. return CMD_RET_FAILURE;
  1977. printf("%7s %10s\n", "Port", "Aggr grp");
  1978. printf("%7d %10d\n", parsed_cmd->port, aggr_grp);
  1979. } else {
  1980. printf("%7s %10s\n", "Port", "Aggr grp");
  1981. for (i = 0; i < VSC9953_MAX_PORTS; i++) {
  1982. if (vsc9953_port_aggr_grp_get(i, &aggr_grp))
  1983. continue;
  1984. printf("%7d %10d\n", i, aggr_grp);
  1985. }
  1986. }
  1987. return CMD_RET_SUCCESS;
  1988. }
  1989. static int vsc9953_port_aggr_set_key_func(struct ethsw_command_def *parsed_cmd)
  1990. {
  1991. int i;
  1992. /* Aggregation group number should be set in parsed_cmd->aggr_grp */
  1993. if (parsed_cmd->aggr_grp == ETHSW_CMD_AGGR_GRP_NONE) {
  1994. printf("Please set an aggregation group value\n");
  1995. return CMD_RET_FAILURE;
  1996. }
  1997. if (!VSC9953_PORT_CHECK(parsed_cmd->aggr_grp)) {
  1998. printf("Invalid aggregation group number: %d\n",
  1999. parsed_cmd->aggr_grp);
  2000. return CMD_RET_FAILURE;
  2001. }
  2002. if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
  2003. if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
  2004. printf("Invalid port number: %d\n", parsed_cmd->port);
  2005. return CMD_RET_FAILURE;
  2006. }
  2007. if (vsc9953_port_aggr_grp_set(parsed_cmd->port,
  2008. parsed_cmd->aggr_grp)) {
  2009. printf("Port %d: failed to set aggr group %d\n",
  2010. parsed_cmd->port, parsed_cmd->aggr_grp);
  2011. }
  2012. } else {
  2013. for (i = 0; i < VSC9953_MAX_PORTS; i++) {
  2014. if (vsc9953_port_aggr_grp_set(i,
  2015. parsed_cmd->aggr_grp)) {
  2016. printf("Port %d: failed to set aggr group %d\n",
  2017. i, parsed_cmd->aggr_grp);
  2018. }
  2019. }
  2020. }
  2021. return CMD_RET_SUCCESS;
  2022. }
  2023. static struct ethsw_command_func vsc9953_cmd_func = {
  2024. .ethsw_name = "L2 Switch VSC9953",
  2025. .port_enable = &vsc9953_port_status_key_func,
  2026. .port_disable = &vsc9953_port_status_key_func,
  2027. .port_show = &vsc9953_port_config_key_func,
  2028. .port_stats = &vsc9953_port_stats_key_func,
  2029. .port_stats_clear = &vsc9953_port_stats_clear_key_func,
  2030. .port_learn = &vsc9953_learn_set_key_func,
  2031. .port_learn_show = &vsc9953_learn_show_key_func,
  2032. .fdb_show = &vsc9953_fdb_show_key_func,
  2033. .fdb_flush = &vsc9953_fdb_flush_key_func,
  2034. .fdb_entry_add = &vsc9953_fdb_entry_add_key_func,
  2035. .fdb_entry_del = &vsc9953_fdb_entry_del_key_func,
  2036. .pvid_show = &vsc9953_pvid_show_key_func,
  2037. .pvid_set = &vsc9953_pvid_set_key_func,
  2038. .vlan_show = &vsc9953_vlan_show_key_func,
  2039. .vlan_set = &vsc9953_vlan_set_key_func,
  2040. .port_untag_show = &vsc9953_port_untag_show_key_func,
  2041. .port_untag_set = &vsc9953_port_untag_set_key_func,
  2042. .port_egr_vlan_show = &vsc9953_egr_vlan_tag_show_key_func,
  2043. .port_egr_vlan_set = &vsc9953_egr_vlan_tag_set_key_func,
  2044. .vlan_learn_show = &vsc9953_vlan_learn_show_key_func,
  2045. .vlan_learn_set = &vsc9953_vlan_learn_set_key_func,
  2046. .port_ingr_filt_show = &vsc9953_ingr_fltr_show_key_func,
  2047. .port_ingr_filt_set = &vsc9953_ingr_fltr_set_key_func,
  2048. .port_aggr_show = &vsc9953_port_aggr_show_key_func,
  2049. .port_aggr_set = &vsc9953_port_aggr_set_key_func,
  2050. };
  2051. #endif /* CONFIG_CMD_ETHSW */
  2052. /*****************************************************************************
  2053. At startup, the default configuration would be:
  2054. - HW learning enabled on all ports; (HW default)
  2055. - All ports are in VLAN 1;
  2056. - All ports are VLAN aware;
  2057. - All ports have POP_COUNT 1;
  2058. - All ports have PVID 1;
  2059. - All ports have TPID 0x8100; (HW default)
  2060. - All ports tag frames classified to all VLANs that are not PVID;
  2061. *****************************************************************************/
  2062. void vsc9953_default_configuration(void)
  2063. {
  2064. int i;
  2065. if (vsc9953_autoage_time_set(VSC9953_DEFAULT_AGE_TIME))
  2066. debug("VSC9953: failed to set AGE time to %d\n",
  2067. VSC9953_DEFAULT_AGE_TIME);
  2068. for (i = 0; i < VSC9953_MAX_VLAN; i++)
  2069. vsc9953_vlan_table_membership_all_set(i, 0);
  2070. vsc9953_port_all_vlan_aware_set(1);
  2071. vsc9953_port_all_vlan_pvid_set(1);
  2072. vsc9953_port_all_vlan_poncnt_set(1);
  2073. vsc9953_vlan_table_membership_all_set(1, 1);
  2074. vsc9953_vlan_ingr_fltr_learn_drop(1);
  2075. vsc9953_port_all_vlan_egress_untagged_set(EGRESS_UNTAG_PVID_AND_ZERO);
  2076. if (vsc9953_aggr_code_set(AGGR_CODE_ALL))
  2077. debug("VSC9953: failed to set default aggregation code mode\n");
  2078. }
  2079. static void vcap_entry2cache_init(u32 target, u32 entry_words)
  2080. {
  2081. int i;
  2082. for (i = 0; i < entry_words; i++) {
  2083. out_le32((unsigned int *)(VSC9953_OFFSET +
  2084. VSC9953_VCAP_CACHE_ENTRY_DAT(target, i)), 0x00);
  2085. out_le32((unsigned int *)(VSC9953_OFFSET +
  2086. VSC9953_VCAP_CACHE_MASK_DAT(target, i)), 0xFF);
  2087. }
  2088. out_le32((unsigned int *)(VSC9953_OFFSET +
  2089. VSC9953_VCAP_CACHE_TG_DAT(target)), 0x00);
  2090. out_le32((unsigned int *)(VSC9953_OFFSET +
  2091. VSC9953_VCAP_CFG_MV_CFG(target)),
  2092. VSC9953_VCAP_CFG_MV_CFG_SIZE(entry_words));
  2093. }
  2094. static void vcap_action2cache_init(u32 target, u32 action_words,
  2095. u32 counter_words)
  2096. {
  2097. int i;
  2098. for (i = 0; i < action_words; i++)
  2099. out_le32((unsigned int *)(VSC9953_OFFSET +
  2100. VSC9953_VCAP_CACHE_ACTION_DAT(target, i)), 0x00);
  2101. for (i = 0; i < counter_words; i++)
  2102. out_le32((unsigned int *)(VSC9953_OFFSET +
  2103. VSC9953_VCAP_CACHE_CNT_DAT(target, i)), 0x00);
  2104. }
  2105. static int vcap_cmd(u32 target, u16 ix, int cmd, int sel, int entry_count)
  2106. {
  2107. u32 tgt = target;
  2108. u32 value = (VSC9953_VCAP_UPDATE_CTRL_UPDATE_CMD(cmd) |
  2109. VSC9953_VCAP_UPDATE_CTRL_UPDATE_ADDR(ix) |
  2110. VSC9953_VCAP_UPDATE_CTRL_UPDATE_SHOT);
  2111. if ((sel & TCAM_SEL_ENTRY) && ix >= entry_count)
  2112. return CMD_RET_FAILURE;
  2113. if (!(sel & TCAM_SEL_ENTRY))
  2114. value |= VSC9953_VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS;
  2115. if (!(sel & TCAM_SEL_ACTION))
  2116. value |= VSC9953_VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS;
  2117. if (!(sel & TCAM_SEL_COUNTER))
  2118. value |= VSC9953_VCAP_UPDATE_CTRL_UPDATE_CNT_DIS;
  2119. out_le32((unsigned int *)(VSC9953_OFFSET +
  2120. VSC9953_VCAP_CFG_UPDATE_CTRL(tgt)), value);
  2121. do {
  2122. value = in_le32((unsigned int *)(VSC9953_OFFSET +
  2123. VSC9953_VCAP_CFG_UPDATE_CTRL(tgt)));
  2124. } while (value & VSC9953_VCAP_UPDATE_CTRL_UPDATE_SHOT);
  2125. return CMD_RET_SUCCESS;
  2126. }
  2127. static void vsc9953_vcap_init(void)
  2128. {
  2129. u32 tgt = VSC9953_ES0;
  2130. int cmd_ret;
  2131. /* write entries */
  2132. vcap_entry2cache_init(tgt, ENTRY_WORDS_ES0);
  2133. cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE, TCAM_SEL_ENTRY,
  2134. ENTRY_WORDS_ES0);
  2135. if (cmd_ret != CMD_RET_SUCCESS)
  2136. debug("VSC9953:%d invalid TCAM_SEL_ENTRY\n",
  2137. __LINE__);
  2138. /* write actions and counters */
  2139. vcap_action2cache_init(tgt, BITS_TO_DWORD(ES0_ACT_WIDTH),
  2140. BITS_TO_DWORD(ES0_CNT_WIDTH));
  2141. out_le32((unsigned int *)(VSC9953_OFFSET +
  2142. VSC9953_VCAP_CFG_MV_CFG(tgt)),
  2143. VSC9953_VCAP_CFG_MV_CFG_SIZE(ES0_ACT_COUNT));
  2144. cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE,
  2145. TCAM_SEL_ACTION | TCAM_SEL_COUNTER, ENTRY_WORDS_ES0);
  2146. if (cmd_ret != CMD_RET_SUCCESS)
  2147. debug("VSC9953:%d invalid TCAM_SEL_ACTION | TCAM_SEL_COUNTER\n",
  2148. __LINE__);
  2149. tgt = VSC9953_IS1;
  2150. /* write entries */
  2151. vcap_entry2cache_init(tgt, ENTRY_WORDS_IS1);
  2152. cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE, TCAM_SEL_ENTRY,
  2153. ENTRY_WORDS_IS1);
  2154. if (cmd_ret != CMD_RET_SUCCESS)
  2155. debug("VSC9953:%d invalid TCAM_SEL_ENTRY\n",
  2156. __LINE__);
  2157. /* write actions and counters */
  2158. vcap_action2cache_init(tgt, BITS_TO_DWORD(IS1_ACT_WIDTH),
  2159. BITS_TO_DWORD(IS1_CNT_WIDTH));
  2160. out_le32((unsigned int *)(VSC9953_OFFSET +
  2161. VSC9953_VCAP_CFG_MV_CFG(tgt)),
  2162. VSC9953_VCAP_CFG_MV_CFG_SIZE(IS1_ACT_COUNT));
  2163. cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE,
  2164. TCAM_SEL_ACTION | TCAM_SEL_COUNTER, ENTRY_WORDS_IS1);
  2165. if (cmd_ret != CMD_RET_SUCCESS)
  2166. debug("VSC9953:%d invalid TCAM_SEL_ACTION | TCAM_SEL_COUNTER\n",
  2167. __LINE__);
  2168. tgt = VSC9953_IS2;
  2169. /* write entries */
  2170. vcap_entry2cache_init(tgt, ENTRY_WORDS_IS2);
  2171. cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE, TCAM_SEL_ENTRY,
  2172. ENTRY_WORDS_IS2);
  2173. if (cmd_ret != CMD_RET_SUCCESS)
  2174. debug("VSC9953:%d invalid selection: TCAM_SEL_ENTRY\n",
  2175. __LINE__);
  2176. /* write actions and counters */
  2177. vcap_action2cache_init(tgt, BITS_TO_DWORD(IS2_ACT_WIDTH),
  2178. BITS_TO_DWORD(IS2_CNT_WIDTH));
  2179. out_le32((unsigned int *)(VSC9953_OFFSET +
  2180. VSC9953_VCAP_CFG_MV_CFG(tgt)),
  2181. VSC9953_VCAP_CFG_MV_CFG_SIZE(IS2_ACT_COUNT));
  2182. cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE,
  2183. TCAM_SEL_ACTION | TCAM_SEL_COUNTER, ENTRY_WORDS_IS2);
  2184. if (cmd_ret != CMD_RET_SUCCESS)
  2185. debug("VSC9953:%d invalid TCAM_SEL_ACTION | TCAM_SEL_COUNTER\n",
  2186. __LINE__);
  2187. }
  2188. void vsc9953_init(struct bd_info *bis)
  2189. {
  2190. u32 i;
  2191. u32 hdx_cfg = 0;
  2192. u32 phy_addr = 0;
  2193. int timeout;
  2194. struct vsc9953_system_reg *l2sys_reg;
  2195. struct vsc9953_qsys_reg *l2qsys_reg;
  2196. struct vsc9953_dev_gmii *l2dev_gmii_reg;
  2197. struct vsc9953_analyzer *l2ana_reg;
  2198. struct vsc9953_devcpu_gcb *l2dev_gcb;
  2199. l2dev_gmii_reg = (struct vsc9953_dev_gmii *)(VSC9953_OFFSET +
  2200. VSC9953_DEV_GMII_OFFSET);
  2201. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  2202. VSC9953_ANA_OFFSET);
  2203. l2sys_reg = (struct vsc9953_system_reg *)(VSC9953_OFFSET +
  2204. VSC9953_SYS_OFFSET);
  2205. l2qsys_reg = (struct vsc9953_qsys_reg *)(VSC9953_OFFSET +
  2206. VSC9953_QSYS_OFFSET);
  2207. l2dev_gcb = (struct vsc9953_devcpu_gcb *)(VSC9953_OFFSET +
  2208. VSC9953_DEVCPU_GCB);
  2209. out_le32(&l2dev_gcb->chip_regs.soft_rst,
  2210. VSC9953_SOFT_SWC_RST_ENA);
  2211. timeout = 50000;
  2212. while ((in_le32(&l2dev_gcb->chip_regs.soft_rst) &
  2213. VSC9953_SOFT_SWC_RST_ENA) && --timeout)
  2214. udelay(1); /* busy wait for vsc9953 soft reset */
  2215. if (timeout == 0)
  2216. debug("Timeout waiting for VSC9953 to reset\n");
  2217. out_le32(&l2sys_reg->sys.reset_cfg, VSC9953_MEM_ENABLE |
  2218. VSC9953_MEM_INIT);
  2219. timeout = 50000;
  2220. while ((in_le32(&l2sys_reg->sys.reset_cfg) &
  2221. VSC9953_MEM_INIT) && --timeout)
  2222. udelay(1); /* busy wait for vsc9953 memory init */
  2223. if (timeout == 0)
  2224. debug("Timeout waiting for VSC9953 memory to initialize\n");
  2225. out_le32(&l2sys_reg->sys.reset_cfg, (in_le32(&l2sys_reg->sys.reset_cfg)
  2226. | VSC9953_CORE_ENABLE));
  2227. /* VSC9953 Setting to be done once only */
  2228. out_le32(&l2qsys_reg->sys.ext_cpu_cfg, 0x00000b00);
  2229. for (i = 0; i < VSC9953_MAX_PORTS; i++) {
  2230. if (vsc9953_port_init(i))
  2231. printf("Failed to initialize l2switch port %d\n", i);
  2232. if (!vsc9953_l2sw.port[i].enabled)
  2233. continue;
  2234. /* Enable VSC9953 GMII Ports Port ID 0 - 7 */
  2235. if (VSC9953_INTERNAL_PORT_CHECK(i)) {
  2236. out_le32(&l2ana_reg->pfc[i].pfc_cfg,
  2237. VSC9953_PFC_FC_QSGMII);
  2238. out_le32(&l2sys_reg->pause_cfg.mac_fc_cfg[i],
  2239. VSC9953_MAC_FC_CFG_QSGMII);
  2240. } else {
  2241. out_le32(&l2ana_reg->pfc[i].pfc_cfg,
  2242. VSC9953_PFC_FC);
  2243. out_le32(&l2sys_reg->pause_cfg.mac_fc_cfg[i],
  2244. VSC9953_MAC_FC_CFG);
  2245. }
  2246. l2dev_gmii_reg = (struct vsc9953_dev_gmii *)
  2247. (VSC9953_OFFSET + VSC9953_DEV_GMII_OFFSET +
  2248. T1040_SWITCH_GMII_DEV_OFFSET * i);
  2249. out_le32(&l2dev_gmii_reg->port_mode.clock_cfg,
  2250. VSC9953_CLOCK_CFG);
  2251. out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_ena_cfg,
  2252. VSC9953_MAC_ENA_CFG);
  2253. out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_mode_cfg,
  2254. VSC9953_MAC_MODE_CFG);
  2255. out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_ifg_cfg,
  2256. VSC9953_MAC_IFG_CFG);
  2257. /* mac_hdx_cfg varies with port id*/
  2258. hdx_cfg = VSC9953_MAC_HDX_CFG | (i << 16);
  2259. out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_hdx_cfg, hdx_cfg);
  2260. out_le32(&l2sys_reg->sys.front_port_mode[i],
  2261. VSC9953_FRONT_PORT_MODE);
  2262. setbits_le32(&l2qsys_reg->sys.switch_port_mode[i],
  2263. VSC9953_PORT_ENA);
  2264. out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_maxlen_cfg,
  2265. VSC9953_MAC_MAX_LEN);
  2266. out_le32(&l2sys_reg->pause_cfg.pause_cfg[i],
  2267. VSC9953_PAUSE_CFG);
  2268. /* WAIT FOR 2 us*/
  2269. udelay(2);
  2270. /* Initialize Lynx PHY Wrappers */
  2271. phy_addr = 0;
  2272. if (vsc9953_l2sw.port[i].enet_if ==
  2273. PHY_INTERFACE_MODE_QSGMII)
  2274. phy_addr = (i + 0x4) & 0x1F;
  2275. else if (vsc9953_l2sw.port[i].enet_if ==
  2276. PHY_INTERFACE_MODE_SGMII)
  2277. phy_addr = (i + 1) & 0x1F;
  2278. if (phy_addr) {
  2279. /* SGMII IF mode + AN enable */
  2280. vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
  2281. 0x14, PHY_SGMII_IF_MODE_AN |
  2282. PHY_SGMII_IF_MODE_SGMII);
  2283. /* Dev ability according to SGMII specification */
  2284. vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
  2285. 0x4, PHY_SGMII_DEV_ABILITY_SGMII);
  2286. /* Adjust link timer for SGMII
  2287. * 1.6 ms in units of 8 ns = 2 * 10^5 = 0x30d40
  2288. */
  2289. vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
  2290. 0x13, 0x0003);
  2291. vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
  2292. 0x12, 0x0d40);
  2293. /* Restart AN */
  2294. vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
  2295. 0x0, PHY_SGMII_CR_DEF_VAL |
  2296. PHY_SGMII_CR_RESET_AN);
  2297. timeout = 50000;
  2298. while ((vsc9953_mdio_read(&l2dev_gcb->mii_mng[0],
  2299. phy_addr, 0x01) & 0x0020) && --timeout)
  2300. udelay(1); /* wait for AN to complete */
  2301. if (timeout == 0)
  2302. debug("Timeout waiting for AN to complete\n");
  2303. }
  2304. }
  2305. vsc9953_vcap_init();
  2306. vsc9953_default_configuration();
  2307. #ifdef CONFIG_CMD_ETHSW
  2308. if (ethsw_define_functions(&vsc9953_cmd_func) < 0)
  2309. debug("Unable to use \"ethsw\" commands\n");
  2310. #endif
  2311. printf("VSC9953 L2 switch initialized\n");
  2312. return;
  2313. }