1f739fcd8STom Rini // SPDX-License-Identifier: GPL-2.0+
26706b115SCodrin Ciubotariu /*
3a857d5f8SCodrin Ciubotariu * Copyright 2014 - 2015 Freescale Semiconductor, Inc.
46706b115SCodrin Ciubotariu *
56706b115SCodrin Ciubotariu * Driver for the Vitesse VSC9953 L2 Switch
66706b115SCodrin Ciubotariu */
76706b115SCodrin Ciubotariu
86706b115SCodrin Ciubotariu #include <asm/io.h>
96706b115SCodrin Ciubotariu #include <asm/fsl_serdes.h>
106706b115SCodrin Ciubotariu #include <fm_eth.h>
11cd348efaSShaohui Xie #include <fsl_memac.h>
129de05987SCodrin Ciubotariu #include <bitfield.h>
133cc8cfffSCodrin Ciubotariu #include <errno.h>
143cc8cfffSCodrin Ciubotariu #include <malloc.h>
156706b115SCodrin Ciubotariu #include <vsc9953.h>
1624a23debSCodrin Ciubotariu #include <ethsw.h>
176706b115SCodrin Ciubotariu
186706b115SCodrin Ciubotariu static struct vsc9953_info vsc9953_l2sw = {
196706b115SCodrin Ciubotariu .port[0] = VSC9953_PORT_INFO_INITIALIZER(0),
206706b115SCodrin Ciubotariu .port[1] = VSC9953_PORT_INFO_INITIALIZER(1),
216706b115SCodrin Ciubotariu .port[2] = VSC9953_PORT_INFO_INITIALIZER(2),
226706b115SCodrin Ciubotariu .port[3] = VSC9953_PORT_INFO_INITIALIZER(3),
236706b115SCodrin Ciubotariu .port[4] = VSC9953_PORT_INFO_INITIALIZER(4),
246706b115SCodrin Ciubotariu .port[5] = VSC9953_PORT_INFO_INITIALIZER(5),
256706b115SCodrin Ciubotariu .port[6] = VSC9953_PORT_INFO_INITIALIZER(6),
266706b115SCodrin Ciubotariu .port[7] = VSC9953_PORT_INFO_INITIALIZER(7),
276706b115SCodrin Ciubotariu .port[8] = VSC9953_PORT_INFO_INITIALIZER(8),
286706b115SCodrin Ciubotariu .port[9] = VSC9953_PORT_INFO_INITIALIZER(9),
296706b115SCodrin Ciubotariu };
306706b115SCodrin Ciubotariu
vsc9953_port_info_set_mdio(int port_no,struct mii_dev * bus)313cc8cfffSCodrin Ciubotariu void vsc9953_port_info_set_mdio(int port_no, struct mii_dev *bus)
326706b115SCodrin Ciubotariu {
333cc8cfffSCodrin Ciubotariu if (!VSC9953_PORT_CHECK(port_no))
346706b115SCodrin Ciubotariu return;
356706b115SCodrin Ciubotariu
363cc8cfffSCodrin Ciubotariu vsc9953_l2sw.port[port_no].bus = bus;
376706b115SCodrin Ciubotariu }
386706b115SCodrin Ciubotariu
vsc9953_port_info_set_phy_address(int port_no,int address)393cc8cfffSCodrin Ciubotariu void vsc9953_port_info_set_phy_address(int port_no, int address)
406706b115SCodrin Ciubotariu {
413cc8cfffSCodrin Ciubotariu if (!VSC9953_PORT_CHECK(port_no))
426706b115SCodrin Ciubotariu return;
436706b115SCodrin Ciubotariu
443cc8cfffSCodrin Ciubotariu vsc9953_l2sw.port[port_no].phyaddr = address;
456706b115SCodrin Ciubotariu }
466706b115SCodrin Ciubotariu
vsc9953_port_info_set_phy_int(int port_no,phy_interface_t phy_int)473cc8cfffSCodrin Ciubotariu void vsc9953_port_info_set_phy_int(int port_no, phy_interface_t phy_int)
486706b115SCodrin Ciubotariu {
493cc8cfffSCodrin Ciubotariu if (!VSC9953_PORT_CHECK(port_no))
506706b115SCodrin Ciubotariu return;
516706b115SCodrin Ciubotariu
523cc8cfffSCodrin Ciubotariu vsc9953_l2sw.port[port_no].enet_if = phy_int;
536706b115SCodrin Ciubotariu }
546706b115SCodrin Ciubotariu
vsc9953_port_enable(int port_no)553cc8cfffSCodrin Ciubotariu void vsc9953_port_enable(int port_no)
566706b115SCodrin Ciubotariu {
573cc8cfffSCodrin Ciubotariu if (!VSC9953_PORT_CHECK(port_no))
586706b115SCodrin Ciubotariu return;
596706b115SCodrin Ciubotariu
603cc8cfffSCodrin Ciubotariu vsc9953_l2sw.port[port_no].enabled = 1;
616706b115SCodrin Ciubotariu }
626706b115SCodrin Ciubotariu
vsc9953_port_disable(int port_no)633cc8cfffSCodrin Ciubotariu void vsc9953_port_disable(int port_no)
646706b115SCodrin Ciubotariu {
653cc8cfffSCodrin Ciubotariu if (!VSC9953_PORT_CHECK(port_no))
666706b115SCodrin Ciubotariu return;
676706b115SCodrin Ciubotariu
683cc8cfffSCodrin Ciubotariu vsc9953_l2sw.port[port_no].enabled = 0;
696706b115SCodrin Ciubotariu }
706706b115SCodrin Ciubotariu
vsc9953_mdio_write(struct vsc9953_mii_mng * phyregs,int port_addr,int regnum,int value)716706b115SCodrin Ciubotariu static void vsc9953_mdio_write(struct vsc9953_mii_mng *phyregs, int port_addr,
726706b115SCodrin Ciubotariu int regnum, int value)
736706b115SCodrin Ciubotariu {
746706b115SCodrin Ciubotariu int timeout = 50000;
756706b115SCodrin Ciubotariu
766706b115SCodrin Ciubotariu out_le32(&phyregs->miimcmd, (0x1 << 31) | ((port_addr & 0x1f) << 25) |
776706b115SCodrin Ciubotariu ((regnum & 0x1f) << 20) | ((value & 0xffff) << 4) |
786706b115SCodrin Ciubotariu (0x1 << 1));
796706b115SCodrin Ciubotariu asm("sync");
806706b115SCodrin Ciubotariu
816706b115SCodrin Ciubotariu while ((in_le32(&phyregs->miimstatus) & 0x8) && --timeout)
826706b115SCodrin Ciubotariu udelay(1);
836706b115SCodrin Ciubotariu
846706b115SCodrin Ciubotariu if (timeout == 0)
856706b115SCodrin Ciubotariu debug("Timeout waiting for MDIO write\n");
866706b115SCodrin Ciubotariu }
876706b115SCodrin Ciubotariu
vsc9953_mdio_read(struct vsc9953_mii_mng * phyregs,int port_addr,int regnum)886706b115SCodrin Ciubotariu static int vsc9953_mdio_read(struct vsc9953_mii_mng *phyregs, int port_addr,
896706b115SCodrin Ciubotariu int regnum)
906706b115SCodrin Ciubotariu {
916706b115SCodrin Ciubotariu int value = 0xFFFF;
926706b115SCodrin Ciubotariu int timeout = 50000;
936706b115SCodrin Ciubotariu
946706b115SCodrin Ciubotariu while ((in_le32(&phyregs->miimstatus) & MIIMIND_OPR_PEND) && --timeout)
956706b115SCodrin Ciubotariu udelay(1);
966706b115SCodrin Ciubotariu if (timeout == 0) {
976706b115SCodrin Ciubotariu debug("Timeout waiting for MDIO operation to finish\n");
986706b115SCodrin Ciubotariu return value;
996706b115SCodrin Ciubotariu }
1006706b115SCodrin Ciubotariu
1016706b115SCodrin Ciubotariu /* Put the address of the phy, and the register
1026706b115SCodrin Ciubotariu * number into MIICMD
1036706b115SCodrin Ciubotariu */
1046706b115SCodrin Ciubotariu out_le32(&phyregs->miimcmd, (0x1 << 31) | ((port_addr & 0x1f) << 25) |
1056706b115SCodrin Ciubotariu ((regnum & 0x1f) << 20) | ((value & 0xffff) << 4) |
1066706b115SCodrin Ciubotariu (0x2 << 1));
1076706b115SCodrin Ciubotariu
1086706b115SCodrin Ciubotariu timeout = 50000;
1096706b115SCodrin Ciubotariu /* Wait for the the indication that the read is done */
1106706b115SCodrin Ciubotariu while ((in_le32(&phyregs->miimstatus) & 0x8) && --timeout)
1116706b115SCodrin Ciubotariu udelay(1);
1126706b115SCodrin Ciubotariu if (timeout == 0)
1136706b115SCodrin Ciubotariu debug("Timeout waiting for MDIO read\n");
1146706b115SCodrin Ciubotariu
1156706b115SCodrin Ciubotariu /* Grab the value read from the PHY */
1166706b115SCodrin Ciubotariu value = in_le32(&phyregs->miimdata);
1176706b115SCodrin Ciubotariu
1186706b115SCodrin Ciubotariu if ((value & 0x00030000) == 0)
1196706b115SCodrin Ciubotariu return value & 0x0000ffff;
1206706b115SCodrin Ciubotariu
1216706b115SCodrin Ciubotariu return value;
1226706b115SCodrin Ciubotariu }
1236706b115SCodrin Ciubotariu
init_phy(struct eth_device * dev)1246706b115SCodrin Ciubotariu static int init_phy(struct eth_device *dev)
1256706b115SCodrin Ciubotariu {
1266706b115SCodrin Ciubotariu struct vsc9953_port_info *l2sw_port = dev->priv;
1276706b115SCodrin Ciubotariu struct phy_device *phydev = NULL;
1286706b115SCodrin Ciubotariu
1296706b115SCodrin Ciubotariu #ifdef CONFIG_PHYLIB
1306706b115SCodrin Ciubotariu if (!l2sw_port->bus)
1316706b115SCodrin Ciubotariu return 0;
1326706b115SCodrin Ciubotariu phydev = phy_connect(l2sw_port->bus, l2sw_port->phyaddr, dev,
1336706b115SCodrin Ciubotariu l2sw_port->enet_if);
1346706b115SCodrin Ciubotariu if (!phydev) {
1356706b115SCodrin Ciubotariu printf("Failed to connect\n");
1366706b115SCodrin Ciubotariu return -1;
1376706b115SCodrin Ciubotariu }
1386706b115SCodrin Ciubotariu
1396706b115SCodrin Ciubotariu phydev->supported &= SUPPORTED_10baseT_Half |
1406706b115SCodrin Ciubotariu SUPPORTED_10baseT_Full |
1416706b115SCodrin Ciubotariu SUPPORTED_100baseT_Half |
1426706b115SCodrin Ciubotariu SUPPORTED_100baseT_Full |
1436706b115SCodrin Ciubotariu SUPPORTED_1000baseT_Full;
1446706b115SCodrin Ciubotariu phydev->advertising = phydev->supported;
1456706b115SCodrin Ciubotariu
1466706b115SCodrin Ciubotariu l2sw_port->phydev = phydev;
1476706b115SCodrin Ciubotariu
1486706b115SCodrin Ciubotariu phy_config(phydev);
1496706b115SCodrin Ciubotariu #endif
1506706b115SCodrin Ciubotariu
1516706b115SCodrin Ciubotariu return 0;
1526706b115SCodrin Ciubotariu }
1536706b115SCodrin Ciubotariu
vsc9953_port_init(int port_no)1543cc8cfffSCodrin Ciubotariu static int vsc9953_port_init(int port_no)
1556706b115SCodrin Ciubotariu {
1566706b115SCodrin Ciubotariu struct eth_device *dev;
1576706b115SCodrin Ciubotariu
1586706b115SCodrin Ciubotariu /* Internal ports never have a PHY */
1593cc8cfffSCodrin Ciubotariu if (VSC9953_INTERNAL_PORT_CHECK(port_no))
1606706b115SCodrin Ciubotariu return 0;
1616706b115SCodrin Ciubotariu
1626706b115SCodrin Ciubotariu /* alloc eth device */
1636706b115SCodrin Ciubotariu dev = (struct eth_device *)calloc(1, sizeof(struct eth_device));
1646706b115SCodrin Ciubotariu if (!dev)
1653cc8cfffSCodrin Ciubotariu return -ENOMEM;
1666706b115SCodrin Ciubotariu
1673cc8cfffSCodrin Ciubotariu sprintf(dev->name, "SW@PORT%d", port_no);
1683cc8cfffSCodrin Ciubotariu dev->priv = &vsc9953_l2sw.port[port_no];
1696706b115SCodrin Ciubotariu dev->init = NULL;
1706706b115SCodrin Ciubotariu dev->halt = NULL;
1716706b115SCodrin Ciubotariu dev->send = NULL;
1726706b115SCodrin Ciubotariu dev->recv = NULL;
1736706b115SCodrin Ciubotariu
1746706b115SCodrin Ciubotariu if (init_phy(dev)) {
1756706b115SCodrin Ciubotariu free(dev);
1763cc8cfffSCodrin Ciubotariu return -ENODEV;
1776706b115SCodrin Ciubotariu }
1786706b115SCodrin Ciubotariu
1796706b115SCodrin Ciubotariu return 0;
1806706b115SCodrin Ciubotariu }
1816706b115SCodrin Ciubotariu
vsc9953_vlan_table_poll_idle(void)1829de05987SCodrin Ciubotariu static int vsc9953_vlan_table_poll_idle(void)
1839de05987SCodrin Ciubotariu {
1849de05987SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
1859de05987SCodrin Ciubotariu int timeout;
1869de05987SCodrin Ciubotariu
1879de05987SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
1889de05987SCodrin Ciubotariu VSC9953_ANA_OFFSET);
1899de05987SCodrin Ciubotariu
1909de05987SCodrin Ciubotariu timeout = 50000;
1919de05987SCodrin Ciubotariu while (((in_le32(&l2ana_reg->ana_tables.vlan_access) &
1929de05987SCodrin Ciubotariu VSC9953_VLAN_CMD_MASK) != VSC9953_VLAN_CMD_IDLE) && --timeout)
1939de05987SCodrin Ciubotariu udelay(1);
1949de05987SCodrin Ciubotariu
1959de05987SCodrin Ciubotariu return timeout ? 0 : -EBUSY;
1969de05987SCodrin Ciubotariu }
1979de05987SCodrin Ciubotariu
198a2477924SCodrin Ciubotariu #ifdef CONFIG_CMD_ETHSW
199a2477924SCodrin Ciubotariu /* Add/remove a port to/from a VLAN */
vsc9953_vlan_table_membership_set(int vid,u32 port_no,u8 add)200a2477924SCodrin Ciubotariu static void vsc9953_vlan_table_membership_set(int vid, u32 port_no, u8 add)
201a2477924SCodrin Ciubotariu {
202a2477924SCodrin Ciubotariu u32 val;
203a2477924SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
204a2477924SCodrin Ciubotariu
205a2477924SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
206a2477924SCodrin Ciubotariu VSC9953_ANA_OFFSET);
207a2477924SCodrin Ciubotariu
208a2477924SCodrin Ciubotariu if (vsc9953_vlan_table_poll_idle() < 0) {
209a2477924SCodrin Ciubotariu debug("VLAN table timeout\n");
210a2477924SCodrin Ciubotariu return;
211a2477924SCodrin Ciubotariu }
212a2477924SCodrin Ciubotariu
213a2477924SCodrin Ciubotariu val = in_le32(&l2ana_reg->ana_tables.vlan_tidx);
214a2477924SCodrin Ciubotariu val = bitfield_replace_by_mask(val, VSC9953_ANA_TBL_VID_MASK, vid);
215a2477924SCodrin Ciubotariu out_le32(&l2ana_reg->ana_tables.vlan_tidx, val);
216a2477924SCodrin Ciubotariu
217a2477924SCodrin Ciubotariu clrsetbits_le32(&l2ana_reg->ana_tables.vlan_access,
218a2477924SCodrin Ciubotariu VSC9953_VLAN_CMD_MASK, VSC9953_VLAN_CMD_READ);
219a2477924SCodrin Ciubotariu
220a2477924SCodrin Ciubotariu if (vsc9953_vlan_table_poll_idle() < 0) {
221a2477924SCodrin Ciubotariu debug("VLAN table timeout\n");
222a2477924SCodrin Ciubotariu return;
223a2477924SCodrin Ciubotariu }
224a2477924SCodrin Ciubotariu
225a2477924SCodrin Ciubotariu val = in_le32(&l2ana_reg->ana_tables.vlan_tidx);
226a2477924SCodrin Ciubotariu val = bitfield_replace_by_mask(val, VSC9953_ANA_TBL_VID_MASK, vid);
227a2477924SCodrin Ciubotariu out_le32(&l2ana_reg->ana_tables.vlan_tidx, val);
228a2477924SCodrin Ciubotariu
229a2477924SCodrin Ciubotariu val = in_le32(&l2ana_reg->ana_tables.vlan_access);
230a2477924SCodrin Ciubotariu if (!add) {
231a2477924SCodrin Ciubotariu val = bitfield_replace_by_mask(val, VSC9953_VLAN_CMD_MASK,
232a2477924SCodrin Ciubotariu VSC9953_VLAN_CMD_WRITE) &
233a2477924SCodrin Ciubotariu ~(bitfield_replace_by_mask(0, VSC9953_VLAN_PORT_MASK,
234a2477924SCodrin Ciubotariu (1 << port_no)));
235a2477924SCodrin Ciubotariu ;
236a2477924SCodrin Ciubotariu } else {
237a2477924SCodrin Ciubotariu val = bitfield_replace_by_mask(val, VSC9953_VLAN_CMD_MASK,
238a2477924SCodrin Ciubotariu VSC9953_VLAN_CMD_WRITE) |
239a2477924SCodrin Ciubotariu bitfield_replace_by_mask(0, VSC9953_VLAN_PORT_MASK,
240a2477924SCodrin Ciubotariu (1 << port_no));
241a2477924SCodrin Ciubotariu }
242a2477924SCodrin Ciubotariu out_le32(&l2ana_reg->ana_tables.vlan_access, val);
243a2477924SCodrin Ciubotariu
244a2477924SCodrin Ciubotariu /* wait for VLAN table command to flush */
245a2477924SCodrin Ciubotariu if (vsc9953_vlan_table_poll_idle() < 0) {
246a2477924SCodrin Ciubotariu debug("VLAN table timeout\n");
247a2477924SCodrin Ciubotariu return;
248a2477924SCodrin Ciubotariu }
249a2477924SCodrin Ciubotariu }
250a2477924SCodrin Ciubotariu
251a2477924SCodrin Ciubotariu /* show VLAN membership for a port */
vsc9953_vlan_membership_show(int port_no)252a2477924SCodrin Ciubotariu static void vsc9953_vlan_membership_show(int port_no)
253a2477924SCodrin Ciubotariu {
254a2477924SCodrin Ciubotariu u32 val;
255a2477924SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
256a2477924SCodrin Ciubotariu u32 vid;
257a2477924SCodrin Ciubotariu
258a2477924SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
259a2477924SCodrin Ciubotariu VSC9953_ANA_OFFSET);
260a2477924SCodrin Ciubotariu
261a2477924SCodrin Ciubotariu printf("Port %d VLAN membership: ", port_no);
262a2477924SCodrin Ciubotariu
263a2477924SCodrin Ciubotariu for (vid = 0; vid < VSC9953_MAX_VLAN; vid++) {
264a2477924SCodrin Ciubotariu if (vsc9953_vlan_table_poll_idle() < 0) {
265a2477924SCodrin Ciubotariu debug("VLAN table timeout\n");
266a2477924SCodrin Ciubotariu return;
267a2477924SCodrin Ciubotariu }
268a2477924SCodrin Ciubotariu
269a2477924SCodrin Ciubotariu val = in_le32(&l2ana_reg->ana_tables.vlan_tidx);
270a2477924SCodrin Ciubotariu val = bitfield_replace_by_mask(val, VSC9953_ANA_TBL_VID_MASK,
271a2477924SCodrin Ciubotariu vid);
272a2477924SCodrin Ciubotariu out_le32(&l2ana_reg->ana_tables.vlan_tidx, val);
273a2477924SCodrin Ciubotariu
274a2477924SCodrin Ciubotariu clrsetbits_le32(&l2ana_reg->ana_tables.vlan_access,
275a2477924SCodrin Ciubotariu VSC9953_VLAN_CMD_MASK, VSC9953_VLAN_CMD_READ);
276a2477924SCodrin Ciubotariu
277a2477924SCodrin Ciubotariu if (vsc9953_vlan_table_poll_idle() < 0) {
278a2477924SCodrin Ciubotariu debug("VLAN table timeout\n");
279a2477924SCodrin Ciubotariu return;
280a2477924SCodrin Ciubotariu }
281a2477924SCodrin Ciubotariu
282a2477924SCodrin Ciubotariu val = in_le32(&l2ana_reg->ana_tables.vlan_access);
283a2477924SCodrin Ciubotariu
284a2477924SCodrin Ciubotariu if (bitfield_extract_by_mask(val, VSC9953_VLAN_PORT_MASK) &
285a2477924SCodrin Ciubotariu (1 << port_no))
286a2477924SCodrin Ciubotariu printf("%d ", vid);
287a2477924SCodrin Ciubotariu }
288a2477924SCodrin Ciubotariu printf("\n");
289a2477924SCodrin Ciubotariu }
290a2477924SCodrin Ciubotariu #endif
291a2477924SCodrin Ciubotariu
2929de05987SCodrin Ciubotariu /* vlan table set/clear all membership of vid */
vsc9953_vlan_table_membership_all_set(int vid,int set_member)2939de05987SCodrin Ciubotariu static void vsc9953_vlan_table_membership_all_set(int vid, int set_member)
2949de05987SCodrin Ciubotariu {
2959de05987SCodrin Ciubotariu uint val;
2969de05987SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
2979de05987SCodrin Ciubotariu
2989de05987SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
2999de05987SCodrin Ciubotariu VSC9953_ANA_OFFSET);
3009de05987SCodrin Ciubotariu
3019de05987SCodrin Ciubotariu if (vsc9953_vlan_table_poll_idle() < 0) {
3029de05987SCodrin Ciubotariu debug("VLAN table timeout\n");
3039de05987SCodrin Ciubotariu return;
3049de05987SCodrin Ciubotariu }
3059de05987SCodrin Ciubotariu
3069de05987SCodrin Ciubotariu /* read current vlan configuration */
3079de05987SCodrin Ciubotariu val = in_le32(&l2ana_reg->ana_tables.vlan_tidx);
3089de05987SCodrin Ciubotariu out_le32(&l2ana_reg->ana_tables.vlan_tidx,
3099de05987SCodrin Ciubotariu bitfield_replace_by_mask(val, VSC9953_ANA_TBL_VID_MASK, vid));
3109de05987SCodrin Ciubotariu
3119de05987SCodrin Ciubotariu clrsetbits_le32(&l2ana_reg->ana_tables.vlan_access,
3129de05987SCodrin Ciubotariu VSC9953_VLAN_CMD_MASK, VSC9953_VLAN_CMD_READ);
3139de05987SCodrin Ciubotariu
3149de05987SCodrin Ciubotariu if (vsc9953_vlan_table_poll_idle() < 0) {
3159de05987SCodrin Ciubotariu debug("VLAN table timeout\n");
3169de05987SCodrin Ciubotariu return;
3179de05987SCodrin Ciubotariu }
3189de05987SCodrin Ciubotariu
3199de05987SCodrin Ciubotariu val = in_le32(&l2ana_reg->ana_tables.vlan_tidx);
3209de05987SCodrin Ciubotariu out_le32(&l2ana_reg->ana_tables.vlan_tidx,
3219de05987SCodrin Ciubotariu bitfield_replace_by_mask(val, VSC9953_ANA_TBL_VID_MASK, vid));
3229de05987SCodrin Ciubotariu
3239de05987SCodrin Ciubotariu clrsetbits_le32(&l2ana_reg->ana_tables.vlan_access,
3249de05987SCodrin Ciubotariu VSC9953_VLAN_PORT_MASK | VSC9953_VLAN_CMD_MASK,
3259de05987SCodrin Ciubotariu VSC9953_VLAN_CMD_WRITE |
3269de05987SCodrin Ciubotariu (set_member ? VSC9953_VLAN_PORT_MASK : 0));
3279de05987SCodrin Ciubotariu }
3289de05987SCodrin Ciubotariu
329a2477924SCodrin Ciubotariu #ifdef CONFIG_CMD_ETHSW
330a2477924SCodrin Ciubotariu /* Get PVID of a VSC9953 port */
vsc9953_port_vlan_pvid_get(int port_nr,int * pvid)331a2477924SCodrin Ciubotariu static int vsc9953_port_vlan_pvid_get(int port_nr, int *pvid)
332a2477924SCodrin Ciubotariu {
333a2477924SCodrin Ciubotariu u32 val;
334a2477924SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
335a2477924SCodrin Ciubotariu
336a2477924SCodrin Ciubotariu /* Administrative down */
3379101a68cSCodrin Ciubotariu if (!vsc9953_l2sw.port[port_nr].enabled) {
338a2477924SCodrin Ciubotariu printf("Port %d is administrative down\n", port_nr);
339a2477924SCodrin Ciubotariu return -1;
340a2477924SCodrin Ciubotariu }
341a2477924SCodrin Ciubotariu
342a2477924SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
343a2477924SCodrin Ciubotariu VSC9953_ANA_OFFSET);
344a2477924SCodrin Ciubotariu
345a2477924SCodrin Ciubotariu /* Get ingress PVID */
346a2477924SCodrin Ciubotariu val = in_le32(&l2ana_reg->port[port_nr].vlan_cfg);
347a2477924SCodrin Ciubotariu *pvid = bitfield_extract_by_mask(val, VSC9953_VLAN_CFG_VID_MASK);
348a2477924SCodrin Ciubotariu
349a2477924SCodrin Ciubotariu return 0;
350a2477924SCodrin Ciubotariu }
351a2477924SCodrin Ciubotariu #endif
352a2477924SCodrin Ciubotariu
3539de05987SCodrin Ciubotariu /* Set PVID for a VSC9953 port */
vsc9953_port_vlan_pvid_set(int port_no,int pvid)3549de05987SCodrin Ciubotariu static void vsc9953_port_vlan_pvid_set(int port_no, int pvid)
3559de05987SCodrin Ciubotariu {
3569de05987SCodrin Ciubotariu uint val;
3579de05987SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
3589de05987SCodrin Ciubotariu struct vsc9953_rew_reg *l2rew_reg;
3599de05987SCodrin Ciubotariu
3609de05987SCodrin Ciubotariu /* Administrative down */
3619de05987SCodrin Ciubotariu if (!vsc9953_l2sw.port[port_no].enabled) {
3629de05987SCodrin Ciubotariu printf("Port %d is administrative down\n", port_no);
3639de05987SCodrin Ciubotariu return;
3649de05987SCodrin Ciubotariu }
3659de05987SCodrin Ciubotariu
3669de05987SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
3679de05987SCodrin Ciubotariu VSC9953_ANA_OFFSET);
3689de05987SCodrin Ciubotariu l2rew_reg = (struct vsc9953_rew_reg *)(VSC9953_OFFSET +
3699de05987SCodrin Ciubotariu VSC9953_REW_OFFSET);
3709de05987SCodrin Ciubotariu
3719de05987SCodrin Ciubotariu /* Set PVID on ingress */
3729de05987SCodrin Ciubotariu val = in_le32(&l2ana_reg->port[port_no].vlan_cfg);
3739de05987SCodrin Ciubotariu val = bitfield_replace_by_mask(val, VSC9953_VLAN_CFG_VID_MASK, pvid);
3749de05987SCodrin Ciubotariu out_le32(&l2ana_reg->port[port_no].vlan_cfg, val);
3759de05987SCodrin Ciubotariu
3769de05987SCodrin Ciubotariu /* Set PVID on egress */
3779de05987SCodrin Ciubotariu val = in_le32(&l2rew_reg->port[port_no].port_vlan_cfg);
3789de05987SCodrin Ciubotariu val = bitfield_replace_by_mask(val, VSC9953_PORT_VLAN_CFG_VID_MASK,
3799de05987SCodrin Ciubotariu pvid);
3809de05987SCodrin Ciubotariu out_le32(&l2rew_reg->port[port_no].port_vlan_cfg, val);
3819de05987SCodrin Ciubotariu }
3829de05987SCodrin Ciubotariu
vsc9953_port_all_vlan_pvid_set(int pvid)3839de05987SCodrin Ciubotariu static void vsc9953_port_all_vlan_pvid_set(int pvid)
3849de05987SCodrin Ciubotariu {
3859de05987SCodrin Ciubotariu int i;
3869de05987SCodrin Ciubotariu
3879de05987SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++)
3889de05987SCodrin Ciubotariu vsc9953_port_vlan_pvid_set(i, pvid);
3899de05987SCodrin Ciubotariu }
3909de05987SCodrin Ciubotariu
3919de05987SCodrin Ciubotariu /* Enable/disable vlan aware of a VSC9953 port */
vsc9953_port_vlan_aware_set(int port_no,int enabled)3929de05987SCodrin Ciubotariu static void vsc9953_port_vlan_aware_set(int port_no, int enabled)
3939de05987SCodrin Ciubotariu {
3949de05987SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
3959de05987SCodrin Ciubotariu
3969de05987SCodrin Ciubotariu /* Administrative down */
3979de05987SCodrin Ciubotariu if (!vsc9953_l2sw.port[port_no].enabled) {
3989de05987SCodrin Ciubotariu printf("Port %d is administrative down\n", port_no);
3999de05987SCodrin Ciubotariu return;
4009de05987SCodrin Ciubotariu }
4019de05987SCodrin Ciubotariu
4029de05987SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
4039de05987SCodrin Ciubotariu VSC9953_ANA_OFFSET);
4049de05987SCodrin Ciubotariu
4059de05987SCodrin Ciubotariu if (enabled)
4069de05987SCodrin Ciubotariu setbits_le32(&l2ana_reg->port[port_no].vlan_cfg,
4079de05987SCodrin Ciubotariu VSC9953_VLAN_CFG_AWARE_ENA);
4089de05987SCodrin Ciubotariu else
4099de05987SCodrin Ciubotariu clrbits_le32(&l2ana_reg->port[port_no].vlan_cfg,
4109de05987SCodrin Ciubotariu VSC9953_VLAN_CFG_AWARE_ENA);
4119de05987SCodrin Ciubotariu }
4129de05987SCodrin Ciubotariu
4139de05987SCodrin Ciubotariu /* Set all VSC9953 ports' vlan aware */
vsc9953_port_all_vlan_aware_set(int enabled)4149de05987SCodrin Ciubotariu static void vsc9953_port_all_vlan_aware_set(int enabled)
4159de05987SCodrin Ciubotariu {
4169de05987SCodrin Ciubotariu int i;
4179de05987SCodrin Ciubotariu
4189de05987SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++)
4199de05987SCodrin Ciubotariu vsc9953_port_vlan_aware_set(i, enabled);
4209de05987SCodrin Ciubotariu }
4219de05987SCodrin Ciubotariu
4229de05987SCodrin Ciubotariu /* Enable/disable vlan pop count of a VSC9953 port */
vsc9953_port_vlan_popcnt_set(int port_no,int popcnt)4239de05987SCodrin Ciubotariu static void vsc9953_port_vlan_popcnt_set(int port_no, int popcnt)
4249de05987SCodrin Ciubotariu {
4259de05987SCodrin Ciubotariu uint val;
4269de05987SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
4279de05987SCodrin Ciubotariu
4289de05987SCodrin Ciubotariu /* Administrative down */
4299de05987SCodrin Ciubotariu if (!vsc9953_l2sw.port[port_no].enabled) {
4309de05987SCodrin Ciubotariu printf("Port %d is administrative down\n", port_no);
4319de05987SCodrin Ciubotariu return;
4329de05987SCodrin Ciubotariu }
4339de05987SCodrin Ciubotariu
4349de05987SCodrin Ciubotariu if (popcnt > 3 || popcnt < 0) {
4359de05987SCodrin Ciubotariu printf("Invalid pop count value: %d\n", port_no);
4369de05987SCodrin Ciubotariu return;
4379de05987SCodrin Ciubotariu }
4389de05987SCodrin Ciubotariu
4399de05987SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
4409de05987SCodrin Ciubotariu VSC9953_ANA_OFFSET);
4419de05987SCodrin Ciubotariu
4429de05987SCodrin Ciubotariu val = in_le32(&l2ana_reg->port[port_no].vlan_cfg);
4439de05987SCodrin Ciubotariu val = bitfield_replace_by_mask(val, VSC9953_VLAN_CFG_POP_CNT_MASK,
4449de05987SCodrin Ciubotariu popcnt);
4459de05987SCodrin Ciubotariu out_le32(&l2ana_reg->port[port_no].vlan_cfg, val);
4469de05987SCodrin Ciubotariu }
4479de05987SCodrin Ciubotariu
4489de05987SCodrin Ciubotariu /* Set all VSC9953 ports' pop count */
vsc9953_port_all_vlan_poncnt_set(int popcnt)4499de05987SCodrin Ciubotariu static void vsc9953_port_all_vlan_poncnt_set(int popcnt)
4509de05987SCodrin Ciubotariu {
4519de05987SCodrin Ciubotariu int i;
4529de05987SCodrin Ciubotariu
4539de05987SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++)
4549de05987SCodrin Ciubotariu vsc9953_port_vlan_popcnt_set(i, popcnt);
4559de05987SCodrin Ciubotariu }
4569de05987SCodrin Ciubotariu
4579de05987SCodrin Ciubotariu /* Enable/disable learning for frames dropped due to ingress filtering */
vsc9953_vlan_ingr_fltr_learn_drop(int enable)4589de05987SCodrin Ciubotariu static void vsc9953_vlan_ingr_fltr_learn_drop(int enable)
4599de05987SCodrin Ciubotariu {
4609de05987SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
4619de05987SCodrin Ciubotariu
4629de05987SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
4639de05987SCodrin Ciubotariu VSC9953_ANA_OFFSET);
4649de05987SCodrin Ciubotariu
4659de05987SCodrin Ciubotariu if (enable)
4669de05987SCodrin Ciubotariu setbits_le32(&l2ana_reg->ana.adv_learn, VSC9953_VLAN_CHK);
4679de05987SCodrin Ciubotariu else
4689de05987SCodrin Ciubotariu clrbits_le32(&l2ana_reg->ana.adv_learn, VSC9953_VLAN_CHK);
4699de05987SCodrin Ciubotariu }
4709de05987SCodrin Ciubotariu
471aae0e689SCodrin Ciubotariu enum aggr_code_mode {
472aae0e689SCodrin Ciubotariu AGGR_CODE_RAND = 0,
473aae0e689SCodrin Ciubotariu AGGR_CODE_ALL, /* S/D MAC, IPv4 S/D IP, IPv6 Flow Label, S/D PORT */
474aae0e689SCodrin Ciubotariu };
475aae0e689SCodrin Ciubotariu
476aae0e689SCodrin Ciubotariu /* Set aggregation code generation mode */
vsc9953_aggr_code_set(enum aggr_code_mode ac)477aae0e689SCodrin Ciubotariu static int vsc9953_aggr_code_set(enum aggr_code_mode ac)
478aae0e689SCodrin Ciubotariu {
479aae0e689SCodrin Ciubotariu int rc;
480aae0e689SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
481aae0e689SCodrin Ciubotariu
482aae0e689SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
483aae0e689SCodrin Ciubotariu VSC9953_ANA_OFFSET);
484aae0e689SCodrin Ciubotariu
485aae0e689SCodrin Ciubotariu switch (ac) {
486aae0e689SCodrin Ciubotariu case AGGR_CODE_RAND:
487aae0e689SCodrin Ciubotariu clrsetbits_le32(&l2ana_reg->common.aggr_cfg,
488aae0e689SCodrin Ciubotariu VSC9953_AC_DMAC_ENA | VSC9953_AC_SMAC_ENA |
489aae0e689SCodrin Ciubotariu VSC9953_AC_IP6_LBL_ENA |
490aae0e689SCodrin Ciubotariu VSC9953_AC_IP6_TCPUDP_ENA |
491aae0e689SCodrin Ciubotariu VSC9953_AC_IP4_SIPDIP_ENA |
492aae0e689SCodrin Ciubotariu VSC9953_AC_IP4_TCPUDP_ENA, VSC9953_AC_RND_ENA);
493aae0e689SCodrin Ciubotariu rc = 0;
494aae0e689SCodrin Ciubotariu break;
495aae0e689SCodrin Ciubotariu case AGGR_CODE_ALL:
496aae0e689SCodrin Ciubotariu clrsetbits_le32(&l2ana_reg->common.aggr_cfg, VSC9953_AC_RND_ENA,
497aae0e689SCodrin Ciubotariu VSC9953_AC_DMAC_ENA | VSC9953_AC_SMAC_ENA |
498aae0e689SCodrin Ciubotariu VSC9953_AC_IP6_LBL_ENA |
499aae0e689SCodrin Ciubotariu VSC9953_AC_IP6_TCPUDP_ENA |
500aae0e689SCodrin Ciubotariu VSC9953_AC_IP4_SIPDIP_ENA |
501aae0e689SCodrin Ciubotariu VSC9953_AC_IP4_TCPUDP_ENA);
502aae0e689SCodrin Ciubotariu rc = 0;
503aae0e689SCodrin Ciubotariu break;
504aae0e689SCodrin Ciubotariu default:
505aae0e689SCodrin Ciubotariu /* unknown mode for aggregation code */
506aae0e689SCodrin Ciubotariu rc = -EINVAL;
507aae0e689SCodrin Ciubotariu }
508aae0e689SCodrin Ciubotariu
509aae0e689SCodrin Ciubotariu return rc;
510aae0e689SCodrin Ciubotariu }
511aae0e689SCodrin Ciubotariu
5129de05987SCodrin Ciubotariu /* Egress untag modes of a VSC9953 port */
5139de05987SCodrin Ciubotariu enum egress_untag_mode {
5149de05987SCodrin Ciubotariu EGRESS_UNTAG_ALL = 0,
5159de05987SCodrin Ciubotariu EGRESS_UNTAG_PVID_AND_ZERO,
5169de05987SCodrin Ciubotariu EGRESS_UNTAG_ZERO,
5179de05987SCodrin Ciubotariu EGRESS_UNTAG_NONE,
5189de05987SCodrin Ciubotariu };
5199de05987SCodrin Ciubotariu
520a2477924SCodrin Ciubotariu #ifdef CONFIG_CMD_ETHSW
521a2477924SCodrin Ciubotariu /* Get egress tagging configuration for a VSC9953 port */
vsc9953_port_vlan_egr_untag_get(int port_no,enum egress_untag_mode * mode)522a2477924SCodrin Ciubotariu static int vsc9953_port_vlan_egr_untag_get(int port_no,
523a2477924SCodrin Ciubotariu enum egress_untag_mode *mode)
524a2477924SCodrin Ciubotariu {
525a2477924SCodrin Ciubotariu u32 val;
526a2477924SCodrin Ciubotariu struct vsc9953_rew_reg *l2rew_reg;
527a2477924SCodrin Ciubotariu
528a2477924SCodrin Ciubotariu /* Administrative down */
529a2477924SCodrin Ciubotariu if (!vsc9953_l2sw.port[port_no].enabled) {
530a2477924SCodrin Ciubotariu printf("Port %d is administrative down\n", port_no);
531a2477924SCodrin Ciubotariu return -1;
532a2477924SCodrin Ciubotariu }
533a2477924SCodrin Ciubotariu
534a2477924SCodrin Ciubotariu l2rew_reg = (struct vsc9953_rew_reg *)(VSC9953_OFFSET +
535a2477924SCodrin Ciubotariu VSC9953_REW_OFFSET);
536a2477924SCodrin Ciubotariu
537a2477924SCodrin Ciubotariu val = in_le32(&l2rew_reg->port[port_no].port_tag_cfg);
538a2477924SCodrin Ciubotariu
539a2477924SCodrin Ciubotariu switch (val & VSC9953_TAG_CFG_MASK) {
540a2477924SCodrin Ciubotariu case VSC9953_TAG_CFG_NONE:
541a2477924SCodrin Ciubotariu *mode = EGRESS_UNTAG_ALL;
542a2477924SCodrin Ciubotariu return 0;
543a2477924SCodrin Ciubotariu case VSC9953_TAG_CFG_ALL_BUT_PVID_ZERO:
544a2477924SCodrin Ciubotariu *mode = EGRESS_UNTAG_PVID_AND_ZERO;
545a2477924SCodrin Ciubotariu return 0;
546a2477924SCodrin Ciubotariu case VSC9953_TAG_CFG_ALL_BUT_ZERO:
547a2477924SCodrin Ciubotariu *mode = EGRESS_UNTAG_ZERO;
548a2477924SCodrin Ciubotariu return 0;
549a2477924SCodrin Ciubotariu case VSC9953_TAG_CFG_ALL:
550a2477924SCodrin Ciubotariu *mode = EGRESS_UNTAG_NONE;
551a2477924SCodrin Ciubotariu return 0;
552a2477924SCodrin Ciubotariu default:
553a2477924SCodrin Ciubotariu printf("Unknown egress tagging configuration for port %d\n",
554a2477924SCodrin Ciubotariu port_no);
555a2477924SCodrin Ciubotariu return -1;
556a2477924SCodrin Ciubotariu }
557a2477924SCodrin Ciubotariu }
558a2477924SCodrin Ciubotariu
559a2477924SCodrin Ciubotariu /* Show egress tagging configuration for a VSC9953 port */
vsc9953_port_vlan_egr_untag_show(int port_no)560a2477924SCodrin Ciubotariu static void vsc9953_port_vlan_egr_untag_show(int port_no)
561a2477924SCodrin Ciubotariu {
562a2477924SCodrin Ciubotariu enum egress_untag_mode mode;
563a2477924SCodrin Ciubotariu
564a2477924SCodrin Ciubotariu if (vsc9953_port_vlan_egr_untag_get(port_no, &mode)) {
565a2477924SCodrin Ciubotariu printf("%7d\t%17s\n", port_no, "-");
566a2477924SCodrin Ciubotariu return;
567a2477924SCodrin Ciubotariu }
568a2477924SCodrin Ciubotariu
569a2477924SCodrin Ciubotariu printf("%7d\t", port_no);
570a2477924SCodrin Ciubotariu switch (mode) {
571a2477924SCodrin Ciubotariu case EGRESS_UNTAG_ALL:
572a2477924SCodrin Ciubotariu printf("%17s\n", "all");
573a2477924SCodrin Ciubotariu break;
574a2477924SCodrin Ciubotariu case EGRESS_UNTAG_NONE:
575a2477924SCodrin Ciubotariu printf("%17s\n", "none");
576a2477924SCodrin Ciubotariu break;
577a2477924SCodrin Ciubotariu case EGRESS_UNTAG_PVID_AND_ZERO:
578a2477924SCodrin Ciubotariu printf("%17s\n", "PVID and 0");
579a2477924SCodrin Ciubotariu break;
580a2477924SCodrin Ciubotariu case EGRESS_UNTAG_ZERO:
581a2477924SCodrin Ciubotariu printf("%17s\n", "0");
582a2477924SCodrin Ciubotariu break;
583a2477924SCodrin Ciubotariu default:
584a2477924SCodrin Ciubotariu printf("%17s\n", "-");
585a2477924SCodrin Ciubotariu }
586a2477924SCodrin Ciubotariu }
587a2477924SCodrin Ciubotariu #endif
588a2477924SCodrin Ciubotariu
vsc9953_port_vlan_egr_untag_set(int port_no,enum egress_untag_mode mode)5899de05987SCodrin Ciubotariu static void vsc9953_port_vlan_egr_untag_set(int port_no,
5909de05987SCodrin Ciubotariu enum egress_untag_mode mode)
5919de05987SCodrin Ciubotariu {
5929de05987SCodrin Ciubotariu struct vsc9953_rew_reg *l2rew_reg;
5939de05987SCodrin Ciubotariu
5949de05987SCodrin Ciubotariu /* Administrative down */
5959de05987SCodrin Ciubotariu if (!vsc9953_l2sw.port[port_no].enabled) {
5969de05987SCodrin Ciubotariu printf("Port %d is administrative down\n", port_no);
5979de05987SCodrin Ciubotariu return;
5989de05987SCodrin Ciubotariu }
5999de05987SCodrin Ciubotariu
6009de05987SCodrin Ciubotariu l2rew_reg = (struct vsc9953_rew_reg *)(VSC9953_OFFSET +
6019de05987SCodrin Ciubotariu VSC9953_REW_OFFSET);
6029de05987SCodrin Ciubotariu
6039de05987SCodrin Ciubotariu switch (mode) {
6049de05987SCodrin Ciubotariu case EGRESS_UNTAG_ALL:
6059de05987SCodrin Ciubotariu clrsetbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
6069de05987SCodrin Ciubotariu VSC9953_TAG_CFG_MASK, VSC9953_TAG_CFG_NONE);
6079de05987SCodrin Ciubotariu break;
6089de05987SCodrin Ciubotariu case EGRESS_UNTAG_PVID_AND_ZERO:
6099de05987SCodrin Ciubotariu clrsetbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
6109de05987SCodrin Ciubotariu VSC9953_TAG_CFG_MASK,
6119de05987SCodrin Ciubotariu VSC9953_TAG_CFG_ALL_BUT_PVID_ZERO);
6129de05987SCodrin Ciubotariu break;
6139de05987SCodrin Ciubotariu case EGRESS_UNTAG_ZERO:
6149de05987SCodrin Ciubotariu clrsetbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
6159de05987SCodrin Ciubotariu VSC9953_TAG_CFG_MASK,
6169de05987SCodrin Ciubotariu VSC9953_TAG_CFG_ALL_BUT_ZERO);
6179de05987SCodrin Ciubotariu break;
6189de05987SCodrin Ciubotariu case EGRESS_UNTAG_NONE:
6199de05987SCodrin Ciubotariu clrsetbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
6209de05987SCodrin Ciubotariu VSC9953_TAG_CFG_MASK, VSC9953_TAG_CFG_ALL);
6219de05987SCodrin Ciubotariu break;
6229de05987SCodrin Ciubotariu default:
6239de05987SCodrin Ciubotariu printf("Unknown untag mode for port %d\n", port_no);
6249de05987SCodrin Ciubotariu }
6259de05987SCodrin Ciubotariu }
6269de05987SCodrin Ciubotariu
vsc9953_port_all_vlan_egress_untagged_set(enum egress_untag_mode mode)6279de05987SCodrin Ciubotariu static void vsc9953_port_all_vlan_egress_untagged_set(
6289de05987SCodrin Ciubotariu enum egress_untag_mode mode)
6299de05987SCodrin Ciubotariu {
6309de05987SCodrin Ciubotariu int i;
6319de05987SCodrin Ciubotariu
6329de05987SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++)
6339de05987SCodrin Ciubotariu vsc9953_port_vlan_egr_untag_set(i, mode);
6349de05987SCodrin Ciubotariu }
6359de05987SCodrin Ciubotariu
vsc9953_autoage_time_set(int age_period)636ba389e65SCodrin Ciubotariu static int vsc9953_autoage_time_set(int age_period)
637ba389e65SCodrin Ciubotariu {
638ba389e65SCodrin Ciubotariu u32 autoage;
639ba389e65SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
640ba389e65SCodrin Ciubotariu
641ba389e65SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
642ba389e65SCodrin Ciubotariu VSC9953_ANA_OFFSET);
643ba389e65SCodrin Ciubotariu
644ba389e65SCodrin Ciubotariu if (age_period < 0 || age_period > VSC9953_AUTOAGE_PERIOD_MASK)
645ba389e65SCodrin Ciubotariu return -EINVAL;
646ba389e65SCodrin Ciubotariu
647ba389e65SCodrin Ciubotariu autoage = bitfield_replace_by_mask(in_le32(&l2ana_reg->ana.auto_age),
648ba389e65SCodrin Ciubotariu VSC9953_AUTOAGE_PERIOD_MASK,
649ba389e65SCodrin Ciubotariu age_period);
650ba389e65SCodrin Ciubotariu out_le32(&l2ana_reg->ana.auto_age, autoage);
651ba389e65SCodrin Ciubotariu
652ba389e65SCodrin Ciubotariu return 0;
653ba389e65SCodrin Ciubotariu }
654ba389e65SCodrin Ciubotariu
65524a23debSCodrin Ciubotariu #ifdef CONFIG_CMD_ETHSW
65624a23debSCodrin Ciubotariu
65724a23debSCodrin Ciubotariu /* Enable/disable status of a VSC9953 port */
vsc9953_port_status_set(int port_no,u8 enabled)65824a23debSCodrin Ciubotariu static void vsc9953_port_status_set(int port_no, u8 enabled)
65924a23debSCodrin Ciubotariu {
66024a23debSCodrin Ciubotariu struct vsc9953_qsys_reg *l2qsys_reg;
66124a23debSCodrin Ciubotariu
66224a23debSCodrin Ciubotariu /* Administrative down */
66324a23debSCodrin Ciubotariu if (!vsc9953_l2sw.port[port_no].enabled)
66424a23debSCodrin Ciubotariu return;
66524a23debSCodrin Ciubotariu
66624a23debSCodrin Ciubotariu l2qsys_reg = (struct vsc9953_qsys_reg *)(VSC9953_OFFSET +
66724a23debSCodrin Ciubotariu VSC9953_QSYS_OFFSET);
66824a23debSCodrin Ciubotariu
66924a23debSCodrin Ciubotariu if (enabled)
67024a23debSCodrin Ciubotariu setbits_le32(&l2qsys_reg->sys.switch_port_mode[port_no],
67124a23debSCodrin Ciubotariu VSC9953_PORT_ENA);
67224a23debSCodrin Ciubotariu else
67324a23debSCodrin Ciubotariu clrbits_le32(&l2qsys_reg->sys.switch_port_mode[port_no],
67424a23debSCodrin Ciubotariu VSC9953_PORT_ENA);
67524a23debSCodrin Ciubotariu }
67624a23debSCodrin Ciubotariu
67724a23debSCodrin Ciubotariu /* Start autonegotiation for a VSC9953 PHY */
vsc9953_phy_autoneg(int port_no)67824a23debSCodrin Ciubotariu static void vsc9953_phy_autoneg(int port_no)
67924a23debSCodrin Ciubotariu {
68024a23debSCodrin Ciubotariu if (!vsc9953_l2sw.port[port_no].phydev)
68124a23debSCodrin Ciubotariu return;
68224a23debSCodrin Ciubotariu
68324a23debSCodrin Ciubotariu if (vsc9953_l2sw.port[port_no].phydev->drv->startup(
68424a23debSCodrin Ciubotariu vsc9953_l2sw.port[port_no].phydev))
68524a23debSCodrin Ciubotariu printf("Failed to start PHY for port %d\n", port_no);
68624a23debSCodrin Ciubotariu }
68724a23debSCodrin Ciubotariu
68824a23debSCodrin Ciubotariu /* Print a VSC9953 port's configuration */
vsc9953_port_config_show(int port_no)68924a23debSCodrin Ciubotariu static void vsc9953_port_config_show(int port_no)
69024a23debSCodrin Ciubotariu {
69124a23debSCodrin Ciubotariu int speed;
69224a23debSCodrin Ciubotariu int duplex;
69324a23debSCodrin Ciubotariu int link;
69424a23debSCodrin Ciubotariu u8 enabled;
69524a23debSCodrin Ciubotariu u32 val;
69624a23debSCodrin Ciubotariu struct vsc9953_qsys_reg *l2qsys_reg;
69724a23debSCodrin Ciubotariu
69824a23debSCodrin Ciubotariu l2qsys_reg = (struct vsc9953_qsys_reg *)(VSC9953_OFFSET +
69924a23debSCodrin Ciubotariu VSC9953_QSYS_OFFSET);
70024a23debSCodrin Ciubotariu
70124a23debSCodrin Ciubotariu val = in_le32(&l2qsys_reg->sys.switch_port_mode[port_no]);
70224a23debSCodrin Ciubotariu enabled = vsc9953_l2sw.port[port_no].enabled &&
70324a23debSCodrin Ciubotariu (val & VSC9953_PORT_ENA);
70424a23debSCodrin Ciubotariu
70524a23debSCodrin Ciubotariu /* internal ports (8 and 9) are fixed */
70624a23debSCodrin Ciubotariu if (VSC9953_INTERNAL_PORT_CHECK(port_no)) {
70724a23debSCodrin Ciubotariu link = 1;
70824a23debSCodrin Ciubotariu speed = SPEED_2500;
70924a23debSCodrin Ciubotariu duplex = DUPLEX_FULL;
71024a23debSCodrin Ciubotariu } else {
71124a23debSCodrin Ciubotariu if (vsc9953_l2sw.port[port_no].phydev) {
71224a23debSCodrin Ciubotariu link = vsc9953_l2sw.port[port_no].phydev->link;
71324a23debSCodrin Ciubotariu speed = vsc9953_l2sw.port[port_no].phydev->speed;
71424a23debSCodrin Ciubotariu duplex = vsc9953_l2sw.port[port_no].phydev->duplex;
71524a23debSCodrin Ciubotariu } else {
71624a23debSCodrin Ciubotariu link = -1;
71724a23debSCodrin Ciubotariu speed = -1;
71824a23debSCodrin Ciubotariu duplex = -1;
71924a23debSCodrin Ciubotariu }
72024a23debSCodrin Ciubotariu }
72124a23debSCodrin Ciubotariu
72224a23debSCodrin Ciubotariu printf("%8d ", port_no);
72324a23debSCodrin Ciubotariu printf("%8s ", enabled == 1 ? "enabled" : "disabled");
72424a23debSCodrin Ciubotariu printf("%8s ", link == 1 ? "up" : "down");
72524a23debSCodrin Ciubotariu
72624a23debSCodrin Ciubotariu switch (speed) {
72724a23debSCodrin Ciubotariu case SPEED_10:
72824a23debSCodrin Ciubotariu printf("%8d ", 10);
72924a23debSCodrin Ciubotariu break;
73024a23debSCodrin Ciubotariu case SPEED_100:
73124a23debSCodrin Ciubotariu printf("%8d ", 100);
73224a23debSCodrin Ciubotariu break;
73324a23debSCodrin Ciubotariu case SPEED_1000:
73424a23debSCodrin Ciubotariu printf("%8d ", 1000);
73524a23debSCodrin Ciubotariu break;
73624a23debSCodrin Ciubotariu case SPEED_2500:
73724a23debSCodrin Ciubotariu printf("%8d ", 2500);
73824a23debSCodrin Ciubotariu break;
73924a23debSCodrin Ciubotariu case SPEED_10000:
74024a23debSCodrin Ciubotariu printf("%8d ", 10000);
74124a23debSCodrin Ciubotariu break;
74224a23debSCodrin Ciubotariu default:
74324a23debSCodrin Ciubotariu printf("%8s ", "-");
74424a23debSCodrin Ciubotariu }
74524a23debSCodrin Ciubotariu
74624a23debSCodrin Ciubotariu printf("%8s\n", duplex == DUPLEX_FULL ? "full" : "half");
74724a23debSCodrin Ciubotariu }
74824a23debSCodrin Ciubotariu
74986719f0cSCodrin Ciubotariu /* Show VSC9953 ports' statistics */
vsc9953_port_statistics_show(int port_no)75086719f0cSCodrin Ciubotariu static void vsc9953_port_statistics_show(int port_no)
75186719f0cSCodrin Ciubotariu {
75286719f0cSCodrin Ciubotariu u32 rx_val;
75386719f0cSCodrin Ciubotariu u32 tx_val;
75486719f0cSCodrin Ciubotariu struct vsc9953_system_reg *l2sys_reg;
75586719f0cSCodrin Ciubotariu
75686719f0cSCodrin Ciubotariu /* Administrative down */
75786719f0cSCodrin Ciubotariu if (!vsc9953_l2sw.port[port_no].enabled) {
75886719f0cSCodrin Ciubotariu printf("Port %d is administrative down\n", port_no);
75986719f0cSCodrin Ciubotariu return;
76086719f0cSCodrin Ciubotariu }
76186719f0cSCodrin Ciubotariu
76286719f0cSCodrin Ciubotariu l2sys_reg = (struct vsc9953_system_reg *)(VSC9953_OFFSET +
76386719f0cSCodrin Ciubotariu VSC9953_SYS_OFFSET);
76486719f0cSCodrin Ciubotariu
76586719f0cSCodrin Ciubotariu printf("Statistics for L2 Switch port %d:\n", port_no);
76686719f0cSCodrin Ciubotariu
76786719f0cSCodrin Ciubotariu /* Set counter view for our port */
76886719f0cSCodrin Ciubotariu out_le32(&l2sys_reg->sys.stat_cfg, port_no);
76986719f0cSCodrin Ciubotariu
77086719f0cSCodrin Ciubotariu #define VSC9953_STATS_PRINTF "%-15s %10u"
77186719f0cSCodrin Ciubotariu
77286719f0cSCodrin Ciubotariu /* Get number of Rx and Tx frames */
77386719f0cSCodrin Ciubotariu rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_short) +
77486719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_frag) +
77586719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_jabber) +
77686719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_long) +
77786719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_64) +
77886719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_65_127) +
77986719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_128_255) +
78086719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_256_511) +
78186719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_512_1023) +
78286719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_1024_1526) +
78386719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_jumbo);
78486719f0cSCodrin Ciubotariu tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_64) +
78586719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_65_127) +
78686719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_128_255) +
78786719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_256_511) +
78886719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_512_1023) +
78986719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_1024_1526) +
79086719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_jumbo);
79186719f0cSCodrin Ciubotariu printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
79286719f0cSCodrin Ciubotariu "Rx frames:", rx_val, "Tx frames:", tx_val);
79386719f0cSCodrin Ciubotariu
79486719f0cSCodrin Ciubotariu /* Get number of Rx and Tx bytes */
79586719f0cSCodrin Ciubotariu rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_oct);
79686719f0cSCodrin Ciubotariu tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_oct);
79786719f0cSCodrin Ciubotariu printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
79886719f0cSCodrin Ciubotariu "Rx bytes:", rx_val, "Tx bytes:", tx_val);
79986719f0cSCodrin Ciubotariu
80086719f0cSCodrin Ciubotariu /* Get number of Rx frames received ok and Tx frames sent ok */
80186719f0cSCodrin Ciubotariu rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_0) +
80286719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_1) +
80386719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_2) +
80486719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_3) +
80586719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_4) +
80686719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_5) +
80786719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_6) +
80886719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_7) +
80986719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_0) +
81086719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_1) +
81186719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_2) +
81286719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_3) +
81386719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_4) +
81486719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_5) +
81586719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_6) +
81686719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_7);
81786719f0cSCodrin Ciubotariu tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_64) +
81886719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_65_127) +
81986719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_128_255) +
82086719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_256_511) +
82186719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_512_1023) +
82286719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_1024_1526) +
82386719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_jumbo);
82486719f0cSCodrin Ciubotariu printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
82586719f0cSCodrin Ciubotariu "Rx frames ok:", rx_val, "Tx frames ok:", tx_val);
82686719f0cSCodrin Ciubotariu
82786719f0cSCodrin Ciubotariu /* Get number of Rx and Tx unicast frames */
82886719f0cSCodrin Ciubotariu rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_uc);
82986719f0cSCodrin Ciubotariu tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_uc);
83086719f0cSCodrin Ciubotariu printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
83186719f0cSCodrin Ciubotariu "Rx unicast:", rx_val, "Tx unicast:", tx_val);
83286719f0cSCodrin Ciubotariu
83386719f0cSCodrin Ciubotariu /* Get number of Rx and Tx broadcast frames */
83486719f0cSCodrin Ciubotariu rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_bc);
83586719f0cSCodrin Ciubotariu tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_bc);
83686719f0cSCodrin Ciubotariu printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
83786719f0cSCodrin Ciubotariu "Rx broadcast:", rx_val, "Tx broadcast:", tx_val);
83886719f0cSCodrin Ciubotariu
83986719f0cSCodrin Ciubotariu /* Get number of Rx and Tx frames of 64B */
84086719f0cSCodrin Ciubotariu rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_64);
84186719f0cSCodrin Ciubotariu tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_64);
84286719f0cSCodrin Ciubotariu printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
84386719f0cSCodrin Ciubotariu "Rx 64B:", rx_val, "Tx 64B:", tx_val);
84486719f0cSCodrin Ciubotariu
84586719f0cSCodrin Ciubotariu /* Get number of Rx and Tx frames with sizes between 65B and 127B */
84686719f0cSCodrin Ciubotariu rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_65_127);
84786719f0cSCodrin Ciubotariu tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_65_127);
84886719f0cSCodrin Ciubotariu printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
84986719f0cSCodrin Ciubotariu "Rx 65B-127B:", rx_val, "Tx 65B-127B:", tx_val);
85086719f0cSCodrin Ciubotariu
85186719f0cSCodrin Ciubotariu /* Get number of Rx and Tx frames with sizes between 128B and 255B */
85286719f0cSCodrin Ciubotariu rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_128_255);
85386719f0cSCodrin Ciubotariu tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_128_255);
85486719f0cSCodrin Ciubotariu printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
85586719f0cSCodrin Ciubotariu "Rx 128B-255B:", rx_val, "Tx 128B-255B:", tx_val);
85686719f0cSCodrin Ciubotariu
85786719f0cSCodrin Ciubotariu /* Get number of Rx and Tx frames with sizes between 256B and 511B */
85886719f0cSCodrin Ciubotariu rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_256_511);
85986719f0cSCodrin Ciubotariu tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_256_511);
86086719f0cSCodrin Ciubotariu printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
86186719f0cSCodrin Ciubotariu "Rx 256B-511B:", rx_val, "Tx 256B-511B:", tx_val);
86286719f0cSCodrin Ciubotariu
86386719f0cSCodrin Ciubotariu /* Get number of Rx and Tx frames with sizes between 512B and 1023B */
86486719f0cSCodrin Ciubotariu rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_512_1023);
86586719f0cSCodrin Ciubotariu tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_512_1023);
86686719f0cSCodrin Ciubotariu printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
86786719f0cSCodrin Ciubotariu "Rx 512B-1023B:", rx_val, "Tx 512B-1023B:", tx_val);
86886719f0cSCodrin Ciubotariu
86986719f0cSCodrin Ciubotariu /* Get number of Rx and Tx frames with sizes between 1024B and 1526B */
87086719f0cSCodrin Ciubotariu rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_1024_1526);
87186719f0cSCodrin Ciubotariu tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_1024_1526);
87286719f0cSCodrin Ciubotariu printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
87386719f0cSCodrin Ciubotariu "Rx 1024B-1526B:", rx_val, "Tx 1024B-1526B:", tx_val);
87486719f0cSCodrin Ciubotariu
87586719f0cSCodrin Ciubotariu /* Get number of Rx and Tx jumbo frames */
87686719f0cSCodrin Ciubotariu rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_jumbo);
87786719f0cSCodrin Ciubotariu tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_jumbo);
87886719f0cSCodrin Ciubotariu printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
87986719f0cSCodrin Ciubotariu "Rx jumbo:", rx_val, "Tx jumbo:", tx_val);
88086719f0cSCodrin Ciubotariu
88186719f0cSCodrin Ciubotariu /* Get number of Rx and Tx dropped frames */
88286719f0cSCodrin Ciubotariu rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_cat_drop) +
88386719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_tail) +
88486719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_0) +
88586719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_1) +
88686719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_2) +
88786719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_3) +
88886719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_4) +
88986719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_5) +
89086719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_6) +
89186719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_7) +
89286719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_0) +
89386719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_1) +
89486719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_2) +
89586719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_3) +
89686719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_4) +
89786719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_5) +
89886719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_6) +
89986719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_7);
90086719f0cSCodrin Ciubotariu tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_drop) +
90186719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_aged);
90286719f0cSCodrin Ciubotariu printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
90386719f0cSCodrin Ciubotariu "Rx drops:", rx_val, "Tx drops:", tx_val);
90486719f0cSCodrin Ciubotariu
90586719f0cSCodrin Ciubotariu /*
90686719f0cSCodrin Ciubotariu * Get number of Rx frames with CRC or alignment errors
90786719f0cSCodrin Ciubotariu * and number of detected Tx collisions
90886719f0cSCodrin Ciubotariu */
90986719f0cSCodrin Ciubotariu rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_crc);
91086719f0cSCodrin Ciubotariu tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_col);
91186719f0cSCodrin Ciubotariu printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
91286719f0cSCodrin Ciubotariu "Rx CRC&align:", rx_val, "Tx coll:", tx_val);
91386719f0cSCodrin Ciubotariu
91486719f0cSCodrin Ciubotariu /*
91586719f0cSCodrin Ciubotariu * Get number of Rx undersized frames and
91686719f0cSCodrin Ciubotariu * number of Tx aged frames
91786719f0cSCodrin Ciubotariu */
91886719f0cSCodrin Ciubotariu rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_short);
91986719f0cSCodrin Ciubotariu tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_aged);
92086719f0cSCodrin Ciubotariu printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
92186719f0cSCodrin Ciubotariu "Rx undersize:", rx_val, "Tx aged:", tx_val);
92286719f0cSCodrin Ciubotariu
92386719f0cSCodrin Ciubotariu /* Get number of Rx oversized frames */
92486719f0cSCodrin Ciubotariu rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_long);
92586719f0cSCodrin Ciubotariu printf(VSC9953_STATS_PRINTF"\n", "Rx oversized:", rx_val);
92686719f0cSCodrin Ciubotariu
92786719f0cSCodrin Ciubotariu /* Get number of Rx fragmented frames */
92886719f0cSCodrin Ciubotariu rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_frag);
92986719f0cSCodrin Ciubotariu printf(VSC9953_STATS_PRINTF"\n", "Rx fragments:", rx_val);
93086719f0cSCodrin Ciubotariu
93186719f0cSCodrin Ciubotariu /* Get number of Rx jabber errors */
93286719f0cSCodrin Ciubotariu rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_jabber);
93386719f0cSCodrin Ciubotariu printf(VSC9953_STATS_PRINTF"\n", "Rx jabbers:", rx_val);
93486719f0cSCodrin Ciubotariu
93586719f0cSCodrin Ciubotariu /*
93686719f0cSCodrin Ciubotariu * Get number of Rx frames filtered due to classification rules or
93786719f0cSCodrin Ciubotariu * no destination ports
93886719f0cSCodrin Ciubotariu */
93986719f0cSCodrin Ciubotariu rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_cat_drop) +
94086719f0cSCodrin Ciubotariu in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_local);
94186719f0cSCodrin Ciubotariu printf(VSC9953_STATS_PRINTF"\n", "Rx filtered:", rx_val);
94286719f0cSCodrin Ciubotariu
94386719f0cSCodrin Ciubotariu printf("\n");
94486719f0cSCodrin Ciubotariu }
94586719f0cSCodrin Ciubotariu
94686719f0cSCodrin Ciubotariu /* Clear statistics for a VSC9953 port */
vsc9953_port_statistics_clear(int port_no)94786719f0cSCodrin Ciubotariu static void vsc9953_port_statistics_clear(int port_no)
94886719f0cSCodrin Ciubotariu {
94986719f0cSCodrin Ciubotariu struct vsc9953_system_reg *l2sys_reg;
95086719f0cSCodrin Ciubotariu
95186719f0cSCodrin Ciubotariu /* Administrative down */
95286719f0cSCodrin Ciubotariu if (!vsc9953_l2sw.port[port_no].enabled) {
95386719f0cSCodrin Ciubotariu printf("Port %d is administrative down\n", port_no);
95486719f0cSCodrin Ciubotariu return;
95586719f0cSCodrin Ciubotariu }
95686719f0cSCodrin Ciubotariu
95786719f0cSCodrin Ciubotariu l2sys_reg = (struct vsc9953_system_reg *)(VSC9953_OFFSET +
95886719f0cSCodrin Ciubotariu VSC9953_SYS_OFFSET);
95986719f0cSCodrin Ciubotariu
96086719f0cSCodrin Ciubotariu /* Clear all counter groups for our ports */
96186719f0cSCodrin Ciubotariu out_le32(&l2sys_reg->sys.stat_cfg, port_no |
96286719f0cSCodrin Ciubotariu VSC9953_STAT_CLEAR_RX | VSC9953_STAT_CLEAR_TX |
96386719f0cSCodrin Ciubotariu VSC9953_STAT_CLEAR_DR);
96486719f0cSCodrin Ciubotariu }
96586719f0cSCodrin Ciubotariu
96668c929daSCodrin Ciubotariu enum port_learn_mode {
96768c929daSCodrin Ciubotariu PORT_LEARN_NONE,
96868c929daSCodrin Ciubotariu PORT_LEARN_AUTO
96968c929daSCodrin Ciubotariu };
97068c929daSCodrin Ciubotariu
97168c929daSCodrin Ciubotariu /* Set learning configuration for a VSC9953 port */
vsc9953_port_learn_mode_set(int port_no,enum port_learn_mode mode)97268c929daSCodrin Ciubotariu static void vsc9953_port_learn_mode_set(int port_no, enum port_learn_mode mode)
97368c929daSCodrin Ciubotariu {
97468c929daSCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
97568c929daSCodrin Ciubotariu
97668c929daSCodrin Ciubotariu /* Administrative down */
97768c929daSCodrin Ciubotariu if (!vsc9953_l2sw.port[port_no].enabled) {
97868c929daSCodrin Ciubotariu printf("Port %d is administrative down\n", port_no);
97968c929daSCodrin Ciubotariu return;
98068c929daSCodrin Ciubotariu }
98168c929daSCodrin Ciubotariu
98268c929daSCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
98368c929daSCodrin Ciubotariu VSC9953_ANA_OFFSET);
98468c929daSCodrin Ciubotariu
98568c929daSCodrin Ciubotariu switch (mode) {
98668c929daSCodrin Ciubotariu case PORT_LEARN_NONE:
98768c929daSCodrin Ciubotariu clrbits_le32(&l2ana_reg->port[port_no].port_cfg,
98868c929daSCodrin Ciubotariu VSC9953_PORT_CFG_LEARN_DROP |
98968c929daSCodrin Ciubotariu VSC9953_PORT_CFG_LEARN_CPU |
99068c929daSCodrin Ciubotariu VSC9953_PORT_CFG_LEARN_AUTO |
99168c929daSCodrin Ciubotariu VSC9953_PORT_CFG_LEARN_ENA);
99268c929daSCodrin Ciubotariu break;
99368c929daSCodrin Ciubotariu case PORT_LEARN_AUTO:
99468c929daSCodrin Ciubotariu clrsetbits_le32(&l2ana_reg->port[port_no].port_cfg,
99568c929daSCodrin Ciubotariu VSC9953_PORT_CFG_LEARN_DROP |
99668c929daSCodrin Ciubotariu VSC9953_PORT_CFG_LEARN_CPU,
99768c929daSCodrin Ciubotariu VSC9953_PORT_CFG_LEARN_ENA |
99868c929daSCodrin Ciubotariu VSC9953_PORT_CFG_LEARN_AUTO);
99968c929daSCodrin Ciubotariu break;
100068c929daSCodrin Ciubotariu default:
100168c929daSCodrin Ciubotariu printf("Unknown learn mode for port %d\n", port_no);
100268c929daSCodrin Ciubotariu }
100368c929daSCodrin Ciubotariu }
100468c929daSCodrin Ciubotariu
100568c929daSCodrin Ciubotariu /* Get learning configuration for a VSC9953 port */
vsc9953_port_learn_mode_get(int port_no,enum port_learn_mode * mode)100668c929daSCodrin Ciubotariu static int vsc9953_port_learn_mode_get(int port_no, enum port_learn_mode *mode)
100768c929daSCodrin Ciubotariu {
100868c929daSCodrin Ciubotariu u32 val;
100968c929daSCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
101068c929daSCodrin Ciubotariu
101168c929daSCodrin Ciubotariu /* Administrative down */
101268c929daSCodrin Ciubotariu if (!vsc9953_l2sw.port[port_no].enabled) {
101368c929daSCodrin Ciubotariu printf("Port %d is administrative down\n", port_no);
101468c929daSCodrin Ciubotariu return -1;
101568c929daSCodrin Ciubotariu }
101668c929daSCodrin Ciubotariu
101768c929daSCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
101868c929daSCodrin Ciubotariu VSC9953_ANA_OFFSET);
101968c929daSCodrin Ciubotariu
102068c929daSCodrin Ciubotariu /* For now we only support HW learning (auto) and no learning */
102168c929daSCodrin Ciubotariu val = in_le32(&l2ana_reg->port[port_no].port_cfg);
102268c929daSCodrin Ciubotariu if ((val & (VSC9953_PORT_CFG_LEARN_ENA |
102368c929daSCodrin Ciubotariu VSC9953_PORT_CFG_LEARN_AUTO)) ==
102468c929daSCodrin Ciubotariu (VSC9953_PORT_CFG_LEARN_ENA | VSC9953_PORT_CFG_LEARN_AUTO))
102568c929daSCodrin Ciubotariu *mode = PORT_LEARN_AUTO;
102668c929daSCodrin Ciubotariu else
102768c929daSCodrin Ciubotariu *mode = PORT_LEARN_NONE;
102868c929daSCodrin Ciubotariu
102968c929daSCodrin Ciubotariu return 0;
103068c929daSCodrin Ciubotariu }
103168c929daSCodrin Ciubotariu
103222449858SCodrin Ciubotariu /* wait for FDB to become available */
vsc9953_mac_table_poll_idle(void)103322449858SCodrin Ciubotariu static int vsc9953_mac_table_poll_idle(void)
103422449858SCodrin Ciubotariu {
103522449858SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
103622449858SCodrin Ciubotariu u32 timeout;
103722449858SCodrin Ciubotariu
103822449858SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
103922449858SCodrin Ciubotariu VSC9953_ANA_OFFSET);
104022449858SCodrin Ciubotariu
104122449858SCodrin Ciubotariu timeout = 50000;
104222449858SCodrin Ciubotariu while (((in_le32(&l2ana_reg->ana_tables.mac_access) &
104322449858SCodrin Ciubotariu VSC9953_MAC_CMD_MASK) !=
104422449858SCodrin Ciubotariu VSC9953_MAC_CMD_IDLE) && --timeout)
104522449858SCodrin Ciubotariu udelay(1);
104622449858SCodrin Ciubotariu
104722449858SCodrin Ciubotariu return timeout ? 0 : -EBUSY;
104822449858SCodrin Ciubotariu }
104922449858SCodrin Ciubotariu
105022449858SCodrin Ciubotariu /* enum describing available commands for the MAC table */
105122449858SCodrin Ciubotariu enum mac_table_cmd {
105222449858SCodrin Ciubotariu MAC_TABLE_READ,
105322449858SCodrin Ciubotariu MAC_TABLE_LOOKUP,
105422449858SCodrin Ciubotariu MAC_TABLE_WRITE,
105522449858SCodrin Ciubotariu MAC_TABLE_LEARN,
105622449858SCodrin Ciubotariu MAC_TABLE_FORGET,
105722449858SCodrin Ciubotariu MAC_TABLE_GET_NEXT,
105822449858SCodrin Ciubotariu MAC_TABLE_AGE,
105922449858SCodrin Ciubotariu };
106022449858SCodrin Ciubotariu
106122449858SCodrin Ciubotariu /* Issues a command to the FDB table */
vsc9953_mac_table_cmd(enum mac_table_cmd cmd)106222449858SCodrin Ciubotariu static int vsc9953_mac_table_cmd(enum mac_table_cmd cmd)
106322449858SCodrin Ciubotariu {
106422449858SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
106522449858SCodrin Ciubotariu
106622449858SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
106722449858SCodrin Ciubotariu VSC9953_ANA_OFFSET);
106822449858SCodrin Ciubotariu
106922449858SCodrin Ciubotariu switch (cmd) {
107022449858SCodrin Ciubotariu case MAC_TABLE_READ:
107122449858SCodrin Ciubotariu clrsetbits_le32(&l2ana_reg->ana_tables.mac_access,
107222449858SCodrin Ciubotariu VSC9953_MAC_CMD_MASK | VSC9953_MAC_CMD_VALID,
107322449858SCodrin Ciubotariu VSC9953_MAC_CMD_READ);
107422449858SCodrin Ciubotariu break;
107522449858SCodrin Ciubotariu case MAC_TABLE_LOOKUP:
107622449858SCodrin Ciubotariu clrsetbits_le32(&l2ana_reg->ana_tables.mac_access,
107722449858SCodrin Ciubotariu VSC9953_MAC_CMD_MASK, VSC9953_MAC_CMD_READ |
107822449858SCodrin Ciubotariu VSC9953_MAC_CMD_VALID);
107922449858SCodrin Ciubotariu break;
108022449858SCodrin Ciubotariu case MAC_TABLE_WRITE:
108122449858SCodrin Ciubotariu clrsetbits_le32(&l2ana_reg->ana_tables.mac_access,
108222449858SCodrin Ciubotariu VSC9953_MAC_CMD_MASK |
108322449858SCodrin Ciubotariu VSC9953_MAC_ENTRYTYPE_MASK,
108422449858SCodrin Ciubotariu VSC9953_MAC_CMD_WRITE |
108522449858SCodrin Ciubotariu VSC9953_MAC_ENTRYTYPE_LOCKED);
108622449858SCodrin Ciubotariu break;
108722449858SCodrin Ciubotariu case MAC_TABLE_LEARN:
108822449858SCodrin Ciubotariu clrsetbits_le32(&l2ana_reg->ana_tables.mac_access,
108922449858SCodrin Ciubotariu VSC9953_MAC_CMD_MASK |
109022449858SCodrin Ciubotariu VSC9953_MAC_ENTRYTYPE_MASK,
109122449858SCodrin Ciubotariu VSC9953_MAC_CMD_LEARN |
109222449858SCodrin Ciubotariu VSC9953_MAC_ENTRYTYPE_LOCKED |
109322449858SCodrin Ciubotariu VSC9953_MAC_CMD_VALID);
109422449858SCodrin Ciubotariu break;
109522449858SCodrin Ciubotariu case MAC_TABLE_FORGET:
109622449858SCodrin Ciubotariu clrsetbits_le32(&l2ana_reg->ana_tables.mac_access,
109722449858SCodrin Ciubotariu VSC9953_MAC_CMD_MASK |
109822449858SCodrin Ciubotariu VSC9953_MAC_ENTRYTYPE_MASK,
109922449858SCodrin Ciubotariu VSC9953_MAC_CMD_FORGET);
110022449858SCodrin Ciubotariu break;
110122449858SCodrin Ciubotariu case MAC_TABLE_GET_NEXT:
110222449858SCodrin Ciubotariu clrsetbits_le32(&l2ana_reg->ana_tables.mac_access,
110322449858SCodrin Ciubotariu VSC9953_MAC_CMD_MASK |
110422449858SCodrin Ciubotariu VSC9953_MAC_ENTRYTYPE_MASK,
110522449858SCodrin Ciubotariu VSC9953_MAC_CMD_NEXT);
110622449858SCodrin Ciubotariu break;
110722449858SCodrin Ciubotariu case MAC_TABLE_AGE:
110822449858SCodrin Ciubotariu clrsetbits_le32(&l2ana_reg->ana_tables.mac_access,
110922449858SCodrin Ciubotariu VSC9953_MAC_CMD_MASK |
111022449858SCodrin Ciubotariu VSC9953_MAC_ENTRYTYPE_MASK,
111122449858SCodrin Ciubotariu VSC9953_MAC_CMD_AGE);
111222449858SCodrin Ciubotariu break;
111322449858SCodrin Ciubotariu default:
111422449858SCodrin Ciubotariu printf("Unknown MAC table command\n");
111522449858SCodrin Ciubotariu }
111622449858SCodrin Ciubotariu
111722449858SCodrin Ciubotariu if (vsc9953_mac_table_poll_idle() < 0) {
111822449858SCodrin Ciubotariu debug("MAC table timeout\n");
111922449858SCodrin Ciubotariu return -1;
112022449858SCodrin Ciubotariu }
112122449858SCodrin Ciubotariu
112222449858SCodrin Ciubotariu return 0;
112322449858SCodrin Ciubotariu }
112422449858SCodrin Ciubotariu
112522449858SCodrin Ciubotariu /* show the FDB entries that correspond to a port and a VLAN */
vsc9953_mac_table_show(int port_no,int vid)112622449858SCodrin Ciubotariu static void vsc9953_mac_table_show(int port_no, int vid)
112722449858SCodrin Ciubotariu {
112822449858SCodrin Ciubotariu int rc[VSC9953_MAX_PORTS];
112922449858SCodrin Ciubotariu enum port_learn_mode mode[VSC9953_MAX_PORTS];
113022449858SCodrin Ciubotariu int i;
113122449858SCodrin Ciubotariu u32 val;
113222449858SCodrin Ciubotariu u32 vlan;
113322449858SCodrin Ciubotariu u32 mach;
113422449858SCodrin Ciubotariu u32 macl;
113522449858SCodrin Ciubotariu u32 dest_indx;
113622449858SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
113722449858SCodrin Ciubotariu
113822449858SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
113922449858SCodrin Ciubotariu VSC9953_ANA_OFFSET);
114022449858SCodrin Ciubotariu
114122449858SCodrin Ciubotariu /* disable auto learning */
114222449858SCodrin Ciubotariu if (port_no == ETHSW_CMD_PORT_ALL) {
114322449858SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++) {
114422449858SCodrin Ciubotariu rc[i] = vsc9953_port_learn_mode_get(i, &mode[i]);
114522449858SCodrin Ciubotariu if (!rc[i] && mode[i] != PORT_LEARN_NONE)
114622449858SCodrin Ciubotariu vsc9953_port_learn_mode_set(i, PORT_LEARN_NONE);
114722449858SCodrin Ciubotariu }
114822449858SCodrin Ciubotariu } else {
114922449858SCodrin Ciubotariu rc[port_no] = vsc9953_port_learn_mode_get(port_no,
115022449858SCodrin Ciubotariu &mode[port_no]);
115122449858SCodrin Ciubotariu if (!rc[port_no] && mode[port_no] != PORT_LEARN_NONE)
115222449858SCodrin Ciubotariu vsc9953_port_learn_mode_set(port_no, PORT_LEARN_NONE);
115322449858SCodrin Ciubotariu }
115422449858SCodrin Ciubotariu
115522449858SCodrin Ciubotariu /* write port and vid to get selected FDB entries */
115622449858SCodrin Ciubotariu val = in_le32(&l2ana_reg->ana.anag_efil);
115722449858SCodrin Ciubotariu if (port_no != ETHSW_CMD_PORT_ALL) {
115822449858SCodrin Ciubotariu val = bitfield_replace_by_mask(val, VSC9953_AGE_PORT_MASK,
115922449858SCodrin Ciubotariu port_no) | VSC9953_AGE_PORT_EN;
116022449858SCodrin Ciubotariu }
116122449858SCodrin Ciubotariu if (vid != ETHSW_CMD_VLAN_ALL) {
116222449858SCodrin Ciubotariu val = bitfield_replace_by_mask(val, VSC9953_AGE_VID_MASK,
116322449858SCodrin Ciubotariu vid) | VSC9953_AGE_VID_EN;
116422449858SCodrin Ciubotariu }
116522449858SCodrin Ciubotariu out_le32(&l2ana_reg->ana.anag_efil, val);
116622449858SCodrin Ciubotariu
116722449858SCodrin Ciubotariu /* set MAC and VLAN to 0 to look from beginning */
116822449858SCodrin Ciubotariu clrbits_le32(&l2ana_reg->ana_tables.mach_data,
116922449858SCodrin Ciubotariu VSC9953_MAC_VID_MASK | VSC9953_MAC_MACH_MASK);
117022449858SCodrin Ciubotariu out_le32(&l2ana_reg->ana_tables.macl_data, 0);
117122449858SCodrin Ciubotariu
117222449858SCodrin Ciubotariu /* get entries */
117322449858SCodrin Ciubotariu printf("%10s %17s %5s %4s\n", "EntryType", "MAC", "PORT", "VID");
117422449858SCodrin Ciubotariu do {
117522449858SCodrin Ciubotariu if (vsc9953_mac_table_cmd(MAC_TABLE_GET_NEXT) < 0) {
117622449858SCodrin Ciubotariu debug("GET NEXT MAC table command failed\n");
117722449858SCodrin Ciubotariu break;
117822449858SCodrin Ciubotariu }
117922449858SCodrin Ciubotariu
118022449858SCodrin Ciubotariu val = in_le32(&l2ana_reg->ana_tables.mac_access);
118122449858SCodrin Ciubotariu
118222449858SCodrin Ciubotariu /* get out when an invalid entry is found */
118322449858SCodrin Ciubotariu if (!(val & VSC9953_MAC_CMD_VALID))
118422449858SCodrin Ciubotariu break;
118522449858SCodrin Ciubotariu
118622449858SCodrin Ciubotariu switch (val & VSC9953_MAC_ENTRYTYPE_MASK) {
118722449858SCodrin Ciubotariu case VSC9953_MAC_ENTRYTYPE_NORMAL:
118822449858SCodrin Ciubotariu printf("%10s ", "Dynamic");
118922449858SCodrin Ciubotariu break;
119022449858SCodrin Ciubotariu case VSC9953_MAC_ENTRYTYPE_LOCKED:
119122449858SCodrin Ciubotariu printf("%10s ", "Static");
119222449858SCodrin Ciubotariu break;
119322449858SCodrin Ciubotariu case VSC9953_MAC_ENTRYTYPE_IPV4MCAST:
119422449858SCodrin Ciubotariu printf("%10s ", "IPv4 Mcast");
119522449858SCodrin Ciubotariu break;
119622449858SCodrin Ciubotariu case VSC9953_MAC_ENTRYTYPE_IPV6MCAST:
119722449858SCodrin Ciubotariu printf("%10s ", "IPv6 Mcast");
119822449858SCodrin Ciubotariu break;
119922449858SCodrin Ciubotariu default:
120022449858SCodrin Ciubotariu printf("%10s ", "Unknown");
120122449858SCodrin Ciubotariu }
120222449858SCodrin Ciubotariu
120322449858SCodrin Ciubotariu dest_indx = bitfield_extract_by_mask(val,
120422449858SCodrin Ciubotariu VSC9953_MAC_DESTIDX_MASK);
120522449858SCodrin Ciubotariu
120622449858SCodrin Ciubotariu val = in_le32(&l2ana_reg->ana_tables.mach_data);
120722449858SCodrin Ciubotariu vlan = bitfield_extract_by_mask(val, VSC9953_MAC_VID_MASK);
120822449858SCodrin Ciubotariu mach = bitfield_extract_by_mask(val, VSC9953_MAC_MACH_MASK);
120922449858SCodrin Ciubotariu macl = in_le32(&l2ana_reg->ana_tables.macl_data);
121022449858SCodrin Ciubotariu
121122449858SCodrin Ciubotariu printf("%02x:%02x:%02x:%02x:%02x:%02x ", (mach >> 8) & 0xff,
121222449858SCodrin Ciubotariu mach & 0xff, (macl >> 24) & 0xff, (macl >> 16) & 0xff,
121322449858SCodrin Ciubotariu (macl >> 8) & 0xff, macl & 0xff);
121422449858SCodrin Ciubotariu printf("%5d ", dest_indx);
121522449858SCodrin Ciubotariu printf("%4d\n", vlan);
121622449858SCodrin Ciubotariu } while (1);
121722449858SCodrin Ciubotariu
121822449858SCodrin Ciubotariu /* set learning mode to previous value */
121922449858SCodrin Ciubotariu if (port_no == ETHSW_CMD_PORT_ALL) {
122022449858SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++) {
122122449858SCodrin Ciubotariu if (!rc[i] && mode[i] != PORT_LEARN_NONE)
122222449858SCodrin Ciubotariu vsc9953_port_learn_mode_set(i, mode[i]);
122322449858SCodrin Ciubotariu }
122422449858SCodrin Ciubotariu } else {
122522449858SCodrin Ciubotariu /* If administrative down, skip */
122622449858SCodrin Ciubotariu if (!rc[port_no] && mode[port_no] != PORT_LEARN_NONE)
122722449858SCodrin Ciubotariu vsc9953_port_learn_mode_set(port_no, mode[port_no]);
122822449858SCodrin Ciubotariu }
122922449858SCodrin Ciubotariu
123022449858SCodrin Ciubotariu /* reset FDB port and VLAN FDB selection */
123122449858SCodrin Ciubotariu clrbits_le32(&l2ana_reg->ana.anag_efil, VSC9953_AGE_PORT_EN |
123222449858SCodrin Ciubotariu VSC9953_AGE_PORT_MASK | VSC9953_AGE_VID_EN |
123322449858SCodrin Ciubotariu VSC9953_AGE_VID_MASK);
123422449858SCodrin Ciubotariu }
123522449858SCodrin Ciubotariu
123622449858SCodrin Ciubotariu /* Add a static FDB entry */
vsc9953_mac_table_add(u8 port_no,uchar mac[6],int vid)123722449858SCodrin Ciubotariu static int vsc9953_mac_table_add(u8 port_no, uchar mac[6], int vid)
123822449858SCodrin Ciubotariu {
123922449858SCodrin Ciubotariu u32 val;
124022449858SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
124122449858SCodrin Ciubotariu
124222449858SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
124322449858SCodrin Ciubotariu VSC9953_ANA_OFFSET);
124422449858SCodrin Ciubotariu
124522449858SCodrin Ciubotariu val = in_le32(&l2ana_reg->ana_tables.mach_data);
124622449858SCodrin Ciubotariu val = bitfield_replace_by_mask(val, VSC9953_MACHDATA_VID_MASK, vid) |
124722449858SCodrin Ciubotariu (mac[0] << 8) | (mac[1] << 0);
124822449858SCodrin Ciubotariu out_le32(&l2ana_reg->ana_tables.mach_data, val);
124922449858SCodrin Ciubotariu
125022449858SCodrin Ciubotariu out_le32(&l2ana_reg->ana_tables.macl_data,
125122449858SCodrin Ciubotariu (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) |
125222449858SCodrin Ciubotariu (mac[5] << 0));
125322449858SCodrin Ciubotariu
125422449858SCodrin Ciubotariu /* set on which port is the MAC address added */
125522449858SCodrin Ciubotariu val = in_le32(&l2ana_reg->ana_tables.mac_access);
125622449858SCodrin Ciubotariu val = bitfield_replace_by_mask(val, VSC9953_MAC_DESTIDX_MASK, port_no);
125722449858SCodrin Ciubotariu out_le32(&l2ana_reg->ana_tables.mac_access, val);
125822449858SCodrin Ciubotariu
125922449858SCodrin Ciubotariu if (vsc9953_mac_table_cmd(MAC_TABLE_LEARN) < 0)
126022449858SCodrin Ciubotariu return -1;
126122449858SCodrin Ciubotariu
126222449858SCodrin Ciubotariu /* check if the MAC address was indeed added */
126322449858SCodrin Ciubotariu val = in_le32(&l2ana_reg->ana_tables.mach_data);
126422449858SCodrin Ciubotariu val = bitfield_replace_by_mask(val, VSC9953_MACHDATA_VID_MASK, vid) |
126522449858SCodrin Ciubotariu (mac[0] << 8) | (mac[1] << 0);
126622449858SCodrin Ciubotariu out_le32(&l2ana_reg->ana_tables.mach_data, val);
126722449858SCodrin Ciubotariu
126822449858SCodrin Ciubotariu out_le32(&l2ana_reg->ana_tables.macl_data,
126922449858SCodrin Ciubotariu (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) |
127022449858SCodrin Ciubotariu (mac[5] << 0));
127122449858SCodrin Ciubotariu
127222449858SCodrin Ciubotariu if (vsc9953_mac_table_cmd(MAC_TABLE_READ) < 0)
127322449858SCodrin Ciubotariu return -1;
127422449858SCodrin Ciubotariu
127522449858SCodrin Ciubotariu val = in_le32(&l2ana_reg->ana_tables.mac_access);
127622449858SCodrin Ciubotariu
127722449858SCodrin Ciubotariu if ((port_no != bitfield_extract_by_mask(val,
127822449858SCodrin Ciubotariu VSC9953_MAC_DESTIDX_MASK))) {
127922449858SCodrin Ciubotariu printf("Failed to add MAC address\n");
128022449858SCodrin Ciubotariu return -1;
128122449858SCodrin Ciubotariu }
128222449858SCodrin Ciubotariu return 0;
128322449858SCodrin Ciubotariu }
128422449858SCodrin Ciubotariu
128522449858SCodrin Ciubotariu /* Delete a FDB entry */
vsc9953_mac_table_del(uchar mac[6],u16 vid)128622449858SCodrin Ciubotariu static int vsc9953_mac_table_del(uchar mac[6], u16 vid)
128722449858SCodrin Ciubotariu {
128822449858SCodrin Ciubotariu u32 val;
128922449858SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
129022449858SCodrin Ciubotariu
129122449858SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
129222449858SCodrin Ciubotariu VSC9953_ANA_OFFSET);
129322449858SCodrin Ciubotariu
129422449858SCodrin Ciubotariu /* check first if MAC entry is present */
129522449858SCodrin Ciubotariu val = in_le32(&l2ana_reg->ana_tables.mach_data);
129622449858SCodrin Ciubotariu val = bitfield_replace_by_mask(val, VSC9953_MACHDATA_VID_MASK, vid) |
129722449858SCodrin Ciubotariu (mac[0] << 8) | (mac[1] << 0);
129822449858SCodrin Ciubotariu out_le32(&l2ana_reg->ana_tables.mach_data, val);
129922449858SCodrin Ciubotariu
130022449858SCodrin Ciubotariu out_le32(&l2ana_reg->ana_tables.macl_data,
130122449858SCodrin Ciubotariu (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) |
130222449858SCodrin Ciubotariu (mac[5] << 0));
130322449858SCodrin Ciubotariu
130422449858SCodrin Ciubotariu if (vsc9953_mac_table_cmd(MAC_TABLE_LOOKUP) < 0) {
130522449858SCodrin Ciubotariu debug("Lookup in the MAC table failed\n");
130622449858SCodrin Ciubotariu return -1;
130722449858SCodrin Ciubotariu }
130822449858SCodrin Ciubotariu
130922449858SCodrin Ciubotariu if (!(in_le32(&l2ana_reg->ana_tables.mac_access) &
131022449858SCodrin Ciubotariu VSC9953_MAC_CMD_VALID)) {
131122449858SCodrin Ciubotariu printf("The MAC address: %02x:%02x:%02x:%02x:%02x:%02x ",
131222449858SCodrin Ciubotariu mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
131322449858SCodrin Ciubotariu printf("VLAN: %d does not exist.\n", vid);
131422449858SCodrin Ciubotariu return -1;
131522449858SCodrin Ciubotariu }
131622449858SCodrin Ciubotariu
131722449858SCodrin Ciubotariu /* FDB entry found, proceed to delete */
131822449858SCodrin Ciubotariu val = in_le32(&l2ana_reg->ana_tables.mach_data);
131922449858SCodrin Ciubotariu val = bitfield_replace_by_mask(val, VSC9953_MACHDATA_VID_MASK, vid) |
132022449858SCodrin Ciubotariu (mac[0] << 8) | (mac[1] << 0);
132122449858SCodrin Ciubotariu out_le32(&l2ana_reg->ana_tables.mach_data, val);
132222449858SCodrin Ciubotariu
132322449858SCodrin Ciubotariu out_le32(&l2ana_reg->ana_tables.macl_data, (mac[2] << 24) |
132422449858SCodrin Ciubotariu (mac[3] << 16) | (mac[4] << 8) | (mac[5] << 0));
132522449858SCodrin Ciubotariu
132622449858SCodrin Ciubotariu if (vsc9953_mac_table_cmd(MAC_TABLE_FORGET) < 0)
132722449858SCodrin Ciubotariu return -1;
132822449858SCodrin Ciubotariu
132922449858SCodrin Ciubotariu /* check if the MAC entry is still in FDB */
133022449858SCodrin Ciubotariu val = in_le32(&l2ana_reg->ana_tables.mach_data);
133122449858SCodrin Ciubotariu val = bitfield_replace_by_mask(val, VSC9953_MACHDATA_VID_MASK, vid) |
133222449858SCodrin Ciubotariu (mac[0] << 8) | (mac[1] << 0);
133322449858SCodrin Ciubotariu out_le32(&l2ana_reg->ana_tables.mach_data, val);
133422449858SCodrin Ciubotariu
133522449858SCodrin Ciubotariu out_le32(&l2ana_reg->ana_tables.macl_data, (mac[2] << 24) |
133622449858SCodrin Ciubotariu (mac[3] << 16) | (mac[4] << 8) | (mac[5] << 0));
133722449858SCodrin Ciubotariu
133822449858SCodrin Ciubotariu if (vsc9953_mac_table_cmd(MAC_TABLE_LOOKUP) < 0) {
133922449858SCodrin Ciubotariu debug("Lookup in the MAC table failed\n");
134022449858SCodrin Ciubotariu return -1;
134122449858SCodrin Ciubotariu }
134222449858SCodrin Ciubotariu if (in_le32(&l2ana_reg->ana_tables.mac_access) &
134322449858SCodrin Ciubotariu VSC9953_MAC_CMD_VALID) {
134422449858SCodrin Ciubotariu printf("Failed to delete MAC address\n");
134522449858SCodrin Ciubotariu return -1;
134622449858SCodrin Ciubotariu }
134722449858SCodrin Ciubotariu
134822449858SCodrin Ciubotariu return 0;
134922449858SCodrin Ciubotariu }
135022449858SCodrin Ciubotariu
135122449858SCodrin Ciubotariu /* age the unlocked entries in FDB */
vsc9953_mac_table_age(int port_no,int vid)135222449858SCodrin Ciubotariu static void vsc9953_mac_table_age(int port_no, int vid)
135322449858SCodrin Ciubotariu {
135422449858SCodrin Ciubotariu int rc[VSC9953_MAX_PORTS];
135522449858SCodrin Ciubotariu enum port_learn_mode mode[VSC9953_MAX_PORTS];
135622449858SCodrin Ciubotariu u32 val;
135722449858SCodrin Ciubotariu int i;
135822449858SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
135922449858SCodrin Ciubotariu
136022449858SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
136122449858SCodrin Ciubotariu VSC9953_ANA_OFFSET);
136222449858SCodrin Ciubotariu
136322449858SCodrin Ciubotariu /* set port and VID for selective aging */
136422449858SCodrin Ciubotariu val = in_le32(&l2ana_reg->ana.anag_efil);
136522449858SCodrin Ciubotariu if (port_no != ETHSW_CMD_PORT_ALL) {
136622449858SCodrin Ciubotariu /* disable auto learning */
136722449858SCodrin Ciubotariu rc[port_no] = vsc9953_port_learn_mode_get(port_no,
136822449858SCodrin Ciubotariu &mode[port_no]);
136922449858SCodrin Ciubotariu if (!rc[port_no] && mode[port_no] != PORT_LEARN_NONE)
137022449858SCodrin Ciubotariu vsc9953_port_learn_mode_set(port_no, PORT_LEARN_NONE);
137122449858SCodrin Ciubotariu
137222449858SCodrin Ciubotariu val = bitfield_replace_by_mask(val, VSC9953_AGE_PORT_MASK,
137322449858SCodrin Ciubotariu port_no) | VSC9953_AGE_PORT_EN;
137422449858SCodrin Ciubotariu } else {
137522449858SCodrin Ciubotariu /* disable auto learning on all ports */
137622449858SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++) {
137722449858SCodrin Ciubotariu rc[i] = vsc9953_port_learn_mode_get(i, &mode[i]);
137822449858SCodrin Ciubotariu if (!rc[i] && mode[i] != PORT_LEARN_NONE)
137922449858SCodrin Ciubotariu vsc9953_port_learn_mode_set(i, PORT_LEARN_NONE);
138022449858SCodrin Ciubotariu }
138122449858SCodrin Ciubotariu }
138222449858SCodrin Ciubotariu
138322449858SCodrin Ciubotariu if (vid != ETHSW_CMD_VLAN_ALL) {
138422449858SCodrin Ciubotariu val = bitfield_replace_by_mask(val, VSC9953_AGE_VID_MASK, vid) |
138522449858SCodrin Ciubotariu VSC9953_AGE_VID_EN;
138622449858SCodrin Ciubotariu }
138722449858SCodrin Ciubotariu out_le32(&l2ana_reg->ana.anag_efil, val);
138822449858SCodrin Ciubotariu
138922449858SCodrin Ciubotariu /* age the dynamic FDB entries */
139022449858SCodrin Ciubotariu vsc9953_mac_table_cmd(MAC_TABLE_AGE);
139122449858SCodrin Ciubotariu
139222449858SCodrin Ciubotariu /* clear previously set port and VID */
139322449858SCodrin Ciubotariu clrbits_le32(&l2ana_reg->ana.anag_efil, VSC9953_AGE_PORT_EN |
139422449858SCodrin Ciubotariu VSC9953_AGE_PORT_MASK | VSC9953_AGE_VID_EN |
139522449858SCodrin Ciubotariu VSC9953_AGE_VID_MASK);
139622449858SCodrin Ciubotariu
139722449858SCodrin Ciubotariu if (port_no != ETHSW_CMD_PORT_ALL) {
139822449858SCodrin Ciubotariu if (!rc[port_no] && mode[port_no] != PORT_LEARN_NONE)
139922449858SCodrin Ciubotariu vsc9953_port_learn_mode_set(port_no, mode[port_no]);
140022449858SCodrin Ciubotariu } else {
140122449858SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++) {
140222449858SCodrin Ciubotariu if (!rc[i] && mode[i] != PORT_LEARN_NONE)
140322449858SCodrin Ciubotariu vsc9953_port_learn_mode_set(i, mode[i]);
140422449858SCodrin Ciubotariu }
140522449858SCodrin Ciubotariu }
140622449858SCodrin Ciubotariu }
140722449858SCodrin Ciubotariu
140822449858SCodrin Ciubotariu /* Delete all the dynamic FDB entries */
vsc9953_mac_table_flush(int port,int vid)140922449858SCodrin Ciubotariu static void vsc9953_mac_table_flush(int port, int vid)
141022449858SCodrin Ciubotariu {
141122449858SCodrin Ciubotariu vsc9953_mac_table_age(port, vid);
141222449858SCodrin Ciubotariu vsc9953_mac_table_age(port, vid);
141322449858SCodrin Ciubotariu }
141422449858SCodrin Ciubotariu
1415a2477924SCodrin Ciubotariu enum egress_vlan_tag {
1416a2477924SCodrin Ciubotariu EGR_TAG_CLASS = 0,
1417a2477924SCodrin Ciubotariu EGR_TAG_PVID,
1418a2477924SCodrin Ciubotariu };
1419a2477924SCodrin Ciubotariu
1420a2477924SCodrin Ciubotariu /* Set egress tag mode for a VSC9953 port */
vsc9953_port_vlan_egress_tag_set(int port_no,enum egress_vlan_tag mode)1421a2477924SCodrin Ciubotariu static void vsc9953_port_vlan_egress_tag_set(int port_no,
1422a2477924SCodrin Ciubotariu enum egress_vlan_tag mode)
1423a2477924SCodrin Ciubotariu {
1424a2477924SCodrin Ciubotariu struct vsc9953_rew_reg *l2rew_reg;
1425a2477924SCodrin Ciubotariu
1426a2477924SCodrin Ciubotariu l2rew_reg = (struct vsc9953_rew_reg *)(VSC9953_OFFSET +
1427a2477924SCodrin Ciubotariu VSC9953_REW_OFFSET);
1428a2477924SCodrin Ciubotariu
1429a2477924SCodrin Ciubotariu switch (mode) {
1430a2477924SCodrin Ciubotariu case EGR_TAG_CLASS:
1431a2477924SCodrin Ciubotariu clrbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
1432a2477924SCodrin Ciubotariu VSC9953_TAG_VID_PVID);
1433a2477924SCodrin Ciubotariu break;
1434a2477924SCodrin Ciubotariu case EGR_TAG_PVID:
1435a2477924SCodrin Ciubotariu setbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
1436a2477924SCodrin Ciubotariu VSC9953_TAG_VID_PVID);
1437a2477924SCodrin Ciubotariu break;
1438a2477924SCodrin Ciubotariu default:
1439a2477924SCodrin Ciubotariu printf("Unknown egress VLAN tag mode for port %d\n", port_no);
1440a2477924SCodrin Ciubotariu }
1441a2477924SCodrin Ciubotariu }
1442a2477924SCodrin Ciubotariu
1443a2477924SCodrin Ciubotariu /* Get egress tag mode for a VSC9953 port */
vsc9953_port_vlan_egress_tag_get(int port_no,enum egress_vlan_tag * mode)1444a2477924SCodrin Ciubotariu static void vsc9953_port_vlan_egress_tag_get(int port_no,
1445a2477924SCodrin Ciubotariu enum egress_vlan_tag *mode)
1446a2477924SCodrin Ciubotariu {
1447a2477924SCodrin Ciubotariu u32 val;
1448a2477924SCodrin Ciubotariu struct vsc9953_rew_reg *l2rew_reg;
1449a2477924SCodrin Ciubotariu
1450a2477924SCodrin Ciubotariu l2rew_reg = (struct vsc9953_rew_reg *)(VSC9953_OFFSET +
1451a2477924SCodrin Ciubotariu VSC9953_REW_OFFSET);
1452a2477924SCodrin Ciubotariu
1453a2477924SCodrin Ciubotariu val = in_le32(&l2rew_reg->port[port_no].port_tag_cfg);
1454a2477924SCodrin Ciubotariu if (val & VSC9953_TAG_VID_PVID)
1455a2477924SCodrin Ciubotariu *mode = EGR_TAG_PVID;
1456a2477924SCodrin Ciubotariu else
1457a2477924SCodrin Ciubotariu *mode = EGR_TAG_CLASS;
1458a2477924SCodrin Ciubotariu }
1459a2477924SCodrin Ciubotariu
146021d214fcSCodrin Ciubotariu /* VSC9953 VLAN learning modes */
146121d214fcSCodrin Ciubotariu enum vlan_learning_mode {
146221d214fcSCodrin Ciubotariu SHARED_VLAN_LEARNING,
146321d214fcSCodrin Ciubotariu PRIVATE_VLAN_LEARNING,
146421d214fcSCodrin Ciubotariu };
146521d214fcSCodrin Ciubotariu
146621d214fcSCodrin Ciubotariu /* Set VLAN learning mode for VSC9953 */
vsc9953_vlan_learning_set(enum vlan_learning_mode lrn_mode)146721d214fcSCodrin Ciubotariu static void vsc9953_vlan_learning_set(enum vlan_learning_mode lrn_mode)
146821d214fcSCodrin Ciubotariu {
146921d214fcSCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
147021d214fcSCodrin Ciubotariu
147121d214fcSCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
147221d214fcSCodrin Ciubotariu VSC9953_ANA_OFFSET);
147321d214fcSCodrin Ciubotariu
147421d214fcSCodrin Ciubotariu switch (lrn_mode) {
147521d214fcSCodrin Ciubotariu case SHARED_VLAN_LEARNING:
147621d214fcSCodrin Ciubotariu setbits_le32(&l2ana_reg->ana.agen_ctrl, VSC9953_FID_MASK_ALL);
147721d214fcSCodrin Ciubotariu break;
147821d214fcSCodrin Ciubotariu case PRIVATE_VLAN_LEARNING:
147921d214fcSCodrin Ciubotariu clrbits_le32(&l2ana_reg->ana.agen_ctrl, VSC9953_FID_MASK_ALL);
148021d214fcSCodrin Ciubotariu break;
148121d214fcSCodrin Ciubotariu default:
148221d214fcSCodrin Ciubotariu printf("Unknown VLAN learn mode\n");
148321d214fcSCodrin Ciubotariu }
148421d214fcSCodrin Ciubotariu }
148521d214fcSCodrin Ciubotariu
148621d214fcSCodrin Ciubotariu /* Get VLAN learning mode for VSC9953 */
vsc9953_vlan_learning_get(enum vlan_learning_mode * lrn_mode)148721d214fcSCodrin Ciubotariu static int vsc9953_vlan_learning_get(enum vlan_learning_mode *lrn_mode)
148821d214fcSCodrin Ciubotariu {
148921d214fcSCodrin Ciubotariu u32 val;
149021d214fcSCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
149121d214fcSCodrin Ciubotariu
149221d214fcSCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
149321d214fcSCodrin Ciubotariu VSC9953_ANA_OFFSET);
149421d214fcSCodrin Ciubotariu
149521d214fcSCodrin Ciubotariu val = in_le32(&l2ana_reg->ana.agen_ctrl);
149621d214fcSCodrin Ciubotariu
149721d214fcSCodrin Ciubotariu if (!(val & VSC9953_FID_MASK_ALL)) {
149821d214fcSCodrin Ciubotariu *lrn_mode = PRIVATE_VLAN_LEARNING;
149921d214fcSCodrin Ciubotariu } else if ((val & VSC9953_FID_MASK_ALL) == VSC9953_FID_MASK_ALL) {
150021d214fcSCodrin Ciubotariu *lrn_mode = SHARED_VLAN_LEARNING;
150121d214fcSCodrin Ciubotariu } else {
150221d214fcSCodrin Ciubotariu printf("Unknown VLAN learning mode\n");
150321d214fcSCodrin Ciubotariu return -EINVAL;
150421d214fcSCodrin Ciubotariu }
150521d214fcSCodrin Ciubotariu
150621d214fcSCodrin Ciubotariu return 0;
150721d214fcSCodrin Ciubotariu }
150821d214fcSCodrin Ciubotariu
15095ed1bacdSCodrin Ciubotariu /* Enable/disable VLAN ingress filtering on a VSC9953 port */
vsc9953_port_ingress_filtering_set(int port_no,int enabled)15105ed1bacdSCodrin Ciubotariu static void vsc9953_port_ingress_filtering_set(int port_no, int enabled)
15115ed1bacdSCodrin Ciubotariu {
15125ed1bacdSCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
15135ed1bacdSCodrin Ciubotariu
15145ed1bacdSCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
15155ed1bacdSCodrin Ciubotariu VSC9953_ANA_OFFSET);
15165ed1bacdSCodrin Ciubotariu
15175ed1bacdSCodrin Ciubotariu if (enabled)
15185ed1bacdSCodrin Ciubotariu setbits_le32(&l2ana_reg->ana.vlan_mask, 1 << port_no);
15195ed1bacdSCodrin Ciubotariu else
15205ed1bacdSCodrin Ciubotariu clrbits_le32(&l2ana_reg->ana.vlan_mask, 1 << port_no);
15215ed1bacdSCodrin Ciubotariu }
15225ed1bacdSCodrin Ciubotariu
15235ed1bacdSCodrin Ciubotariu /* Return VLAN ingress filtering on a VSC9953 port */
vsc9953_port_ingress_filtering_get(int port_no)15245ed1bacdSCodrin Ciubotariu static int vsc9953_port_ingress_filtering_get(int port_no)
15255ed1bacdSCodrin Ciubotariu {
15265ed1bacdSCodrin Ciubotariu u32 val;
15275ed1bacdSCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
15285ed1bacdSCodrin Ciubotariu
15295ed1bacdSCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
15305ed1bacdSCodrin Ciubotariu VSC9953_ANA_OFFSET);
15315ed1bacdSCodrin Ciubotariu
15325ed1bacdSCodrin Ciubotariu val = in_le32(&l2ana_reg->ana.vlan_mask);
15335ed1bacdSCodrin Ciubotariu return !!(val & (1 << port_no));
15345ed1bacdSCodrin Ciubotariu }
15355ed1bacdSCodrin Ciubotariu
1536aae0e689SCodrin Ciubotariu /* Get the aggregation group of a port */
vsc9953_port_aggr_grp_get(int port_no,int * aggr_grp)1537aae0e689SCodrin Ciubotariu static int vsc9953_port_aggr_grp_get(int port_no, int *aggr_grp)
1538aae0e689SCodrin Ciubotariu {
1539aae0e689SCodrin Ciubotariu u32 val;
1540aae0e689SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
1541aae0e689SCodrin Ciubotariu
1542aae0e689SCodrin Ciubotariu if (!VSC9953_PORT_CHECK(port_no))
1543aae0e689SCodrin Ciubotariu return -EINVAL;
1544aae0e689SCodrin Ciubotariu
1545aae0e689SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
1546aae0e689SCodrin Ciubotariu VSC9953_ANA_OFFSET);
1547aae0e689SCodrin Ciubotariu
1548aae0e689SCodrin Ciubotariu val = in_le32(&l2ana_reg->port[port_no].port_cfg);
1549aae0e689SCodrin Ciubotariu *aggr_grp = bitfield_extract_by_mask(val,
1550aae0e689SCodrin Ciubotariu VSC9953_PORT_CFG_PORTID_MASK);
1551aae0e689SCodrin Ciubotariu
1552aae0e689SCodrin Ciubotariu return 0;
1553aae0e689SCodrin Ciubotariu }
1554aae0e689SCodrin Ciubotariu
vsc9953_aggr_grp_members_get(int aggr_grp,u8 aggr_membr[VSC9953_MAX_PORTS])1555aae0e689SCodrin Ciubotariu static void vsc9953_aggr_grp_members_get(int aggr_grp,
1556aae0e689SCodrin Ciubotariu u8 aggr_membr[VSC9953_MAX_PORTS])
1557aae0e689SCodrin Ciubotariu {
1558aae0e689SCodrin Ciubotariu int port_no;
1559aae0e689SCodrin Ciubotariu int aggr_membr_grp;
1560aae0e689SCodrin Ciubotariu
1561aae0e689SCodrin Ciubotariu for (port_no = 0; port_no < VSC9953_MAX_PORTS; port_no++) {
1562aae0e689SCodrin Ciubotariu aggr_membr[port_no] = 0;
1563aae0e689SCodrin Ciubotariu
1564aae0e689SCodrin Ciubotariu if (vsc9953_port_aggr_grp_get(port_no, &aggr_membr_grp))
1565aae0e689SCodrin Ciubotariu continue;
1566aae0e689SCodrin Ciubotariu
1567aae0e689SCodrin Ciubotariu if (aggr_grp == aggr_membr_grp)
1568aae0e689SCodrin Ciubotariu aggr_membr[port_no] = 1;
1569aae0e689SCodrin Ciubotariu }
1570aae0e689SCodrin Ciubotariu }
1571aae0e689SCodrin Ciubotariu
vsc9953_update_dest_members_masks(int port_no,u32 membr_bitfld_old,u32 membr_bitfld_new)1572aae0e689SCodrin Ciubotariu static void vsc9953_update_dest_members_masks(int port_no, u32 membr_bitfld_old,
1573aae0e689SCodrin Ciubotariu u32 membr_bitfld_new)
1574aae0e689SCodrin Ciubotariu {
1575aae0e689SCodrin Ciubotariu int i;
1576aae0e689SCodrin Ciubotariu u32 pgid;
1577aae0e689SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
1578aae0e689SCodrin Ciubotariu
1579aae0e689SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
1580aae0e689SCodrin Ciubotariu VSC9953_ANA_OFFSET);
1581aae0e689SCodrin Ciubotariu
1582aae0e689SCodrin Ciubotariu /*
1583aae0e689SCodrin Ciubotariu * NOTE: Only the unicast destination masks are updated, since
1584aae0e689SCodrin Ciubotariu * we do not support for now Layer-2 multicast entries
1585aae0e689SCodrin Ciubotariu */
1586aae0e689SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++) {
1587aae0e689SCodrin Ciubotariu if (i == port_no) {
1588aae0e689SCodrin Ciubotariu clrsetbits_le32(&l2ana_reg->port_id_tbl.port_grp_id[i],
1589aae0e689SCodrin Ciubotariu VSC9953_PGID_PORT_MASK,
1590aae0e689SCodrin Ciubotariu membr_bitfld_new);
1591aae0e689SCodrin Ciubotariu continue;
1592aae0e689SCodrin Ciubotariu }
1593aae0e689SCodrin Ciubotariu
1594aae0e689SCodrin Ciubotariu pgid = in_le32(&l2ana_reg->port_id_tbl.port_grp_id[i]);
1595aae0e689SCodrin Ciubotariu if ((u32)(1 << i) & membr_bitfld_old & VSC9953_PGID_PORT_MASK)
1596aae0e689SCodrin Ciubotariu pgid &= ~((u32)(1 << port_no));
1597aae0e689SCodrin Ciubotariu if ((u32)(1 << i) & membr_bitfld_new & VSC9953_PGID_PORT_MASK)
1598aae0e689SCodrin Ciubotariu pgid |= ((u32)(1 << port_no));
1599aae0e689SCodrin Ciubotariu
1600aae0e689SCodrin Ciubotariu out_le32(&l2ana_reg->port_id_tbl.port_grp_id[i], pgid);
1601aae0e689SCodrin Ciubotariu }
1602aae0e689SCodrin Ciubotariu }
1603aae0e689SCodrin Ciubotariu
vsc9953_update_source_members_masks(int port_no,u32 membr_bitfld_old,u32 membr_bitfld_new)1604aae0e689SCodrin Ciubotariu static void vsc9953_update_source_members_masks(int port_no,
1605aae0e689SCodrin Ciubotariu u32 membr_bitfld_old,
1606aae0e689SCodrin Ciubotariu u32 membr_bitfld_new)
1607aae0e689SCodrin Ciubotariu {
1608aae0e689SCodrin Ciubotariu int i;
1609aae0e689SCodrin Ciubotariu int index;
1610aae0e689SCodrin Ciubotariu u32 pgid;
1611aae0e689SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
1612aae0e689SCodrin Ciubotariu
1613aae0e689SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
1614aae0e689SCodrin Ciubotariu VSC9953_ANA_OFFSET);
1615aae0e689SCodrin Ciubotariu
1616aae0e689SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS + 1; i++) {
1617aae0e689SCodrin Ciubotariu index = PGID_SRC_START + i;
1618aae0e689SCodrin Ciubotariu pgid = in_le32(&l2ana_reg->port_id_tbl.port_grp_id[index]);
1619aae0e689SCodrin Ciubotariu if (i == port_no) {
1620aae0e689SCodrin Ciubotariu pgid = (pgid | VSC9953_PGID_PORT_MASK) &
1621aae0e689SCodrin Ciubotariu ~membr_bitfld_new;
1622aae0e689SCodrin Ciubotariu out_le32(&l2ana_reg->port_id_tbl.port_grp_id[index],
1623aae0e689SCodrin Ciubotariu pgid);
1624aae0e689SCodrin Ciubotariu continue;
1625aae0e689SCodrin Ciubotariu }
1626aae0e689SCodrin Ciubotariu
1627aae0e689SCodrin Ciubotariu if ((u32)(1 << i) & membr_bitfld_old & VSC9953_PGID_PORT_MASK)
1628aae0e689SCodrin Ciubotariu pgid |= (u32)(1 << port_no);
1629aae0e689SCodrin Ciubotariu
1630aae0e689SCodrin Ciubotariu if ((u32)(1 << i) & membr_bitfld_new & VSC9953_PGID_PORT_MASK)
1631aae0e689SCodrin Ciubotariu pgid &= ~(u32)(1 << port_no);
1632aae0e689SCodrin Ciubotariu out_le32(&l2ana_reg->port_id_tbl.port_grp_id[index], pgid);
1633aae0e689SCodrin Ciubotariu }
1634aae0e689SCodrin Ciubotariu }
1635aae0e689SCodrin Ciubotariu
vsc9953_aggr_mask_get_next(u32 aggr_mask,u32 member_bitfield)1636aae0e689SCodrin Ciubotariu static u32 vsc9953_aggr_mask_get_next(u32 aggr_mask, u32 member_bitfield)
1637aae0e689SCodrin Ciubotariu {
1638aae0e689SCodrin Ciubotariu if (!member_bitfield)
1639aae0e689SCodrin Ciubotariu return 0;
1640aae0e689SCodrin Ciubotariu
1641aae0e689SCodrin Ciubotariu if (!(aggr_mask & VSC9953_PGID_PORT_MASK))
1642aae0e689SCodrin Ciubotariu aggr_mask = 1;
1643aae0e689SCodrin Ciubotariu else
1644aae0e689SCodrin Ciubotariu aggr_mask <<= 1;
1645aae0e689SCodrin Ciubotariu
1646aae0e689SCodrin Ciubotariu while (!(aggr_mask & member_bitfield)) {
1647aae0e689SCodrin Ciubotariu aggr_mask <<= 1;
1648aae0e689SCodrin Ciubotariu if (!(aggr_mask & VSC9953_PGID_PORT_MASK))
1649aae0e689SCodrin Ciubotariu aggr_mask = 1;
1650aae0e689SCodrin Ciubotariu }
1651aae0e689SCodrin Ciubotariu
1652aae0e689SCodrin Ciubotariu return aggr_mask;
1653aae0e689SCodrin Ciubotariu }
1654aae0e689SCodrin Ciubotariu
vsc9953_update_aggr_members_masks(int port_no,u32 membr_bitfld_old,u32 membr_bitfld_new)1655aae0e689SCodrin Ciubotariu static void vsc9953_update_aggr_members_masks(int port_no, u32 membr_bitfld_old,
1656aae0e689SCodrin Ciubotariu u32 membr_bitfld_new)
1657aae0e689SCodrin Ciubotariu {
1658aae0e689SCodrin Ciubotariu int i;
1659aae0e689SCodrin Ciubotariu u32 pgid;
1660aae0e689SCodrin Ciubotariu u32 aggr_mask_old = 0;
1661aae0e689SCodrin Ciubotariu u32 aggr_mask_new = 0;
1662aae0e689SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
1663aae0e689SCodrin Ciubotariu
1664aae0e689SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
1665aae0e689SCodrin Ciubotariu VSC9953_ANA_OFFSET);
1666aae0e689SCodrin Ciubotariu
1667aae0e689SCodrin Ciubotariu /* Update all the PGID aggregation masks */
1668aae0e689SCodrin Ciubotariu for (i = PGID_AGGR_START; i < PGID_SRC_START; i++) {
1669aae0e689SCodrin Ciubotariu pgid = in_le32(&l2ana_reg->port_id_tbl.port_grp_id[i]);
1670aae0e689SCodrin Ciubotariu
1671aae0e689SCodrin Ciubotariu aggr_mask_old = vsc9953_aggr_mask_get_next(aggr_mask_old,
1672aae0e689SCodrin Ciubotariu membr_bitfld_old);
1673aae0e689SCodrin Ciubotariu pgid = (pgid & ~membr_bitfld_old) | aggr_mask_old;
1674aae0e689SCodrin Ciubotariu
1675aae0e689SCodrin Ciubotariu aggr_mask_new = vsc9953_aggr_mask_get_next(aggr_mask_new,
1676aae0e689SCodrin Ciubotariu membr_bitfld_new);
1677aae0e689SCodrin Ciubotariu pgid = (pgid & ~membr_bitfld_new) | aggr_mask_new;
1678aae0e689SCodrin Ciubotariu
1679aae0e689SCodrin Ciubotariu out_le32(&l2ana_reg->port_id_tbl.port_grp_id[i], pgid);
1680aae0e689SCodrin Ciubotariu }
1681aae0e689SCodrin Ciubotariu }
1682aae0e689SCodrin Ciubotariu
vsc9953_aggr_membr_bitfield_get(u8 member[VSC9953_MAX_PORTS])1683aae0e689SCodrin Ciubotariu static u32 vsc9953_aggr_membr_bitfield_get(u8 member[VSC9953_MAX_PORTS])
1684aae0e689SCodrin Ciubotariu {
1685aae0e689SCodrin Ciubotariu int i;
1686aae0e689SCodrin Ciubotariu u32 member_bitfield = 0;
1687aae0e689SCodrin Ciubotariu
1688aae0e689SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++) {
1689aae0e689SCodrin Ciubotariu if (member[i])
1690aae0e689SCodrin Ciubotariu member_bitfield |= 1 << i;
1691aae0e689SCodrin Ciubotariu }
1692aae0e689SCodrin Ciubotariu member_bitfield &= VSC9953_PGID_PORT_MASK;
1693aae0e689SCodrin Ciubotariu
1694aae0e689SCodrin Ciubotariu return member_bitfield;
1695aae0e689SCodrin Ciubotariu }
1696aae0e689SCodrin Ciubotariu
vsc9953_update_members_masks(int port_no,u8 member_old[VSC9953_MAX_PORTS],u8 member_new[VSC9953_MAX_PORTS])1697aae0e689SCodrin Ciubotariu static void vsc9953_update_members_masks(int port_no,
1698aae0e689SCodrin Ciubotariu u8 member_old[VSC9953_MAX_PORTS],
1699aae0e689SCodrin Ciubotariu u8 member_new[VSC9953_MAX_PORTS])
1700aae0e689SCodrin Ciubotariu {
1701aae0e689SCodrin Ciubotariu u32 membr_bitfld_old = vsc9953_aggr_membr_bitfield_get(member_old);
1702aae0e689SCodrin Ciubotariu u32 membr_bitfld_new = vsc9953_aggr_membr_bitfield_get(member_new);
1703aae0e689SCodrin Ciubotariu
1704aae0e689SCodrin Ciubotariu vsc9953_update_dest_members_masks(port_no, membr_bitfld_old,
1705aae0e689SCodrin Ciubotariu membr_bitfld_new);
1706aae0e689SCodrin Ciubotariu vsc9953_update_source_members_masks(port_no, membr_bitfld_old,
1707aae0e689SCodrin Ciubotariu membr_bitfld_new);
1708aae0e689SCodrin Ciubotariu vsc9953_update_aggr_members_masks(port_no, membr_bitfld_old,
1709aae0e689SCodrin Ciubotariu membr_bitfld_new);
1710aae0e689SCodrin Ciubotariu }
1711aae0e689SCodrin Ciubotariu
1712aae0e689SCodrin Ciubotariu /* Set the aggregation group of a port */
vsc9953_port_aggr_grp_set(int port_no,int aggr_grp)1713aae0e689SCodrin Ciubotariu static int vsc9953_port_aggr_grp_set(int port_no, int aggr_grp)
1714aae0e689SCodrin Ciubotariu {
1715aae0e689SCodrin Ciubotariu u8 aggr_membr_old[VSC9953_MAX_PORTS];
1716aae0e689SCodrin Ciubotariu u8 aggr_membr_new[VSC9953_MAX_PORTS];
1717aae0e689SCodrin Ciubotariu int rc;
1718aae0e689SCodrin Ciubotariu int aggr_grp_old;
1719aae0e689SCodrin Ciubotariu u32 val;
1720aae0e689SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
1721aae0e689SCodrin Ciubotariu
1722aae0e689SCodrin Ciubotariu if (!VSC9953_PORT_CHECK(port_no) || !VSC9953_PORT_CHECK(aggr_grp))
1723aae0e689SCodrin Ciubotariu return -EINVAL;
1724aae0e689SCodrin Ciubotariu
1725aae0e689SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
1726aae0e689SCodrin Ciubotariu VSC9953_ANA_OFFSET);
1727aae0e689SCodrin Ciubotariu
1728aae0e689SCodrin Ciubotariu rc = vsc9953_port_aggr_grp_get(port_no, &aggr_grp_old);
1729aae0e689SCodrin Ciubotariu if (rc)
1730aae0e689SCodrin Ciubotariu return rc;
1731aae0e689SCodrin Ciubotariu
1732aae0e689SCodrin Ciubotariu /* get all the members of the old aggregation group */
1733aae0e689SCodrin Ciubotariu vsc9953_aggr_grp_members_get(aggr_grp_old, aggr_membr_old);
1734aae0e689SCodrin Ciubotariu
1735aae0e689SCodrin Ciubotariu /* get all the members of the same aggregation group */
1736aae0e689SCodrin Ciubotariu vsc9953_aggr_grp_members_get(aggr_grp, aggr_membr_new);
1737aae0e689SCodrin Ciubotariu
1738aae0e689SCodrin Ciubotariu /* add current port as member to the new aggregation group */
1739aae0e689SCodrin Ciubotariu aggr_membr_old[port_no] = 0;
1740aae0e689SCodrin Ciubotariu aggr_membr_new[port_no] = 1;
1741aae0e689SCodrin Ciubotariu
1742aae0e689SCodrin Ciubotariu /* update masks */
1743aae0e689SCodrin Ciubotariu vsc9953_update_members_masks(port_no, aggr_membr_old, aggr_membr_new);
1744aae0e689SCodrin Ciubotariu
1745aae0e689SCodrin Ciubotariu /* Change logical port number */
1746aae0e689SCodrin Ciubotariu val = in_le32(&l2ana_reg->port[port_no].port_cfg);
1747aae0e689SCodrin Ciubotariu val = bitfield_replace_by_mask(val,
1748aae0e689SCodrin Ciubotariu VSC9953_PORT_CFG_PORTID_MASK, aggr_grp);
1749aae0e689SCodrin Ciubotariu out_le32(&l2ana_reg->port[port_no].port_cfg, val);
1750aae0e689SCodrin Ciubotariu
1751aae0e689SCodrin Ciubotariu return 0;
1752aae0e689SCodrin Ciubotariu }
1753aae0e689SCodrin Ciubotariu
vsc9953_port_status_key_func(struct ethsw_command_def * parsed_cmd)175424a23debSCodrin Ciubotariu static int vsc9953_port_status_key_func(struct ethsw_command_def *parsed_cmd)
175524a23debSCodrin Ciubotariu {
175624a23debSCodrin Ciubotariu int i;
175724a23debSCodrin Ciubotariu u8 enabled;
175824a23debSCodrin Ciubotariu
175924a23debSCodrin Ciubotariu /* Last keyword should tell us if we should enable/disable the port */
176024a23debSCodrin Ciubotariu if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
176124a23debSCodrin Ciubotariu ethsw_id_enable)
176224a23debSCodrin Ciubotariu enabled = 1;
176324a23debSCodrin Ciubotariu else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
176424a23debSCodrin Ciubotariu ethsw_id_disable)
176524a23debSCodrin Ciubotariu enabled = 0;
176624a23debSCodrin Ciubotariu else
176724a23debSCodrin Ciubotariu return CMD_RET_USAGE;
176824a23debSCodrin Ciubotariu
176924a23debSCodrin Ciubotariu if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
177024a23debSCodrin Ciubotariu if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
177124a23debSCodrin Ciubotariu printf("Invalid port number: %d\n", parsed_cmd->port);
177224a23debSCodrin Ciubotariu return CMD_RET_FAILURE;
177324a23debSCodrin Ciubotariu }
177424a23debSCodrin Ciubotariu vsc9953_port_status_set(parsed_cmd->port, enabled);
177524a23debSCodrin Ciubotariu } else {
177624a23debSCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++)
177724a23debSCodrin Ciubotariu vsc9953_port_status_set(i, enabled);
177824a23debSCodrin Ciubotariu }
177924a23debSCodrin Ciubotariu
178024a23debSCodrin Ciubotariu return CMD_RET_SUCCESS;
178124a23debSCodrin Ciubotariu }
178224a23debSCodrin Ciubotariu
vsc9953_port_config_key_func(struct ethsw_command_def * parsed_cmd)178324a23debSCodrin Ciubotariu static int vsc9953_port_config_key_func(struct ethsw_command_def *parsed_cmd)
178424a23debSCodrin Ciubotariu {
178524a23debSCodrin Ciubotariu int i;
178624a23debSCodrin Ciubotariu
178724a23debSCodrin Ciubotariu if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
178824a23debSCodrin Ciubotariu if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
178924a23debSCodrin Ciubotariu printf("Invalid port number: %d\n", parsed_cmd->port);
179024a23debSCodrin Ciubotariu return CMD_RET_FAILURE;
179124a23debSCodrin Ciubotariu }
179224a23debSCodrin Ciubotariu vsc9953_phy_autoneg(parsed_cmd->port);
179324a23debSCodrin Ciubotariu printf("%8s %8s %8s %8s %8s\n",
179424a23debSCodrin Ciubotariu "Port", "Status", "Link", "Speed",
179524a23debSCodrin Ciubotariu "Duplex");
179624a23debSCodrin Ciubotariu vsc9953_port_config_show(parsed_cmd->port);
179724a23debSCodrin Ciubotariu
179824a23debSCodrin Ciubotariu } else {
179924a23debSCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++)
180024a23debSCodrin Ciubotariu vsc9953_phy_autoneg(i);
180124a23debSCodrin Ciubotariu printf("%8s %8s %8s %8s %8s\n",
180224a23debSCodrin Ciubotariu "Port", "Status", "Link", "Speed", "Duplex");
180324a23debSCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++)
180424a23debSCodrin Ciubotariu vsc9953_port_config_show(i);
180524a23debSCodrin Ciubotariu }
180624a23debSCodrin Ciubotariu
180724a23debSCodrin Ciubotariu return CMD_RET_SUCCESS;
180824a23debSCodrin Ciubotariu }
180924a23debSCodrin Ciubotariu
vsc9953_port_stats_key_func(struct ethsw_command_def * parsed_cmd)181086719f0cSCodrin Ciubotariu static int vsc9953_port_stats_key_func(struct ethsw_command_def *parsed_cmd)
181186719f0cSCodrin Ciubotariu {
181286719f0cSCodrin Ciubotariu int i;
181386719f0cSCodrin Ciubotariu
181486719f0cSCodrin Ciubotariu if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
181586719f0cSCodrin Ciubotariu if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
181686719f0cSCodrin Ciubotariu printf("Invalid port number: %d\n", parsed_cmd->port);
181786719f0cSCodrin Ciubotariu return CMD_RET_FAILURE;
181886719f0cSCodrin Ciubotariu }
181986719f0cSCodrin Ciubotariu vsc9953_port_statistics_show(parsed_cmd->port);
182086719f0cSCodrin Ciubotariu } else {
182186719f0cSCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++)
182286719f0cSCodrin Ciubotariu vsc9953_port_statistics_show(i);
182386719f0cSCodrin Ciubotariu }
182486719f0cSCodrin Ciubotariu
182586719f0cSCodrin Ciubotariu return CMD_RET_SUCCESS;
182686719f0cSCodrin Ciubotariu }
182786719f0cSCodrin Ciubotariu
vsc9953_port_stats_clear_key_func(struct ethsw_command_def * parsed_cmd)182886719f0cSCodrin Ciubotariu static int vsc9953_port_stats_clear_key_func(struct ethsw_command_def
182986719f0cSCodrin Ciubotariu *parsed_cmd)
183086719f0cSCodrin Ciubotariu {
183186719f0cSCodrin Ciubotariu int i;
183286719f0cSCodrin Ciubotariu
183386719f0cSCodrin Ciubotariu if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
183486719f0cSCodrin Ciubotariu if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
183586719f0cSCodrin Ciubotariu printf("Invalid port number: %d\n", parsed_cmd->port);
183686719f0cSCodrin Ciubotariu return CMD_RET_FAILURE;
183786719f0cSCodrin Ciubotariu }
183886719f0cSCodrin Ciubotariu vsc9953_port_statistics_clear(parsed_cmd->port);
183986719f0cSCodrin Ciubotariu } else {
184086719f0cSCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++)
184186719f0cSCodrin Ciubotariu vsc9953_port_statistics_clear(i);
184286719f0cSCodrin Ciubotariu }
184386719f0cSCodrin Ciubotariu
184486719f0cSCodrin Ciubotariu return CMD_RET_SUCCESS;
184586719f0cSCodrin Ciubotariu }
184686719f0cSCodrin Ciubotariu
vsc9953_learn_show_key_func(struct ethsw_command_def * parsed_cmd)184768c929daSCodrin Ciubotariu static int vsc9953_learn_show_key_func(struct ethsw_command_def *parsed_cmd)
184868c929daSCodrin Ciubotariu {
184968c929daSCodrin Ciubotariu int i;
185068c929daSCodrin Ciubotariu enum port_learn_mode mode;
185168c929daSCodrin Ciubotariu
185268c929daSCodrin Ciubotariu if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
185368c929daSCodrin Ciubotariu if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
185468c929daSCodrin Ciubotariu printf("Invalid port number: %d\n", parsed_cmd->port);
185568c929daSCodrin Ciubotariu return CMD_RET_FAILURE;
185668c929daSCodrin Ciubotariu }
185768c929daSCodrin Ciubotariu if (vsc9953_port_learn_mode_get(parsed_cmd->port, &mode))
185868c929daSCodrin Ciubotariu return CMD_RET_FAILURE;
185968c929daSCodrin Ciubotariu printf("%7s %11s\n", "Port", "Learn mode");
186068c929daSCodrin Ciubotariu switch (mode) {
186168c929daSCodrin Ciubotariu case PORT_LEARN_NONE:
186268c929daSCodrin Ciubotariu printf("%7d %11s\n", parsed_cmd->port, "disable");
186368c929daSCodrin Ciubotariu break;
186468c929daSCodrin Ciubotariu case PORT_LEARN_AUTO:
186568c929daSCodrin Ciubotariu printf("%7d %11s\n", parsed_cmd->port, "auto");
186668c929daSCodrin Ciubotariu break;
186768c929daSCodrin Ciubotariu default:
186868c929daSCodrin Ciubotariu printf("%7d %11s\n", parsed_cmd->port, "-");
186968c929daSCodrin Ciubotariu }
187068c929daSCodrin Ciubotariu } else {
187168c929daSCodrin Ciubotariu printf("%7s %11s\n", "Port", "Learn mode");
187268c929daSCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++) {
187368c929daSCodrin Ciubotariu if (vsc9953_port_learn_mode_get(i, &mode))
187468c929daSCodrin Ciubotariu continue;
187568c929daSCodrin Ciubotariu switch (mode) {
187668c929daSCodrin Ciubotariu case PORT_LEARN_NONE:
187768c929daSCodrin Ciubotariu printf("%7d %11s\n", i, "disable");
187868c929daSCodrin Ciubotariu break;
187968c929daSCodrin Ciubotariu case PORT_LEARN_AUTO:
188068c929daSCodrin Ciubotariu printf("%7d %11s\n", i, "auto");
188168c929daSCodrin Ciubotariu break;
188268c929daSCodrin Ciubotariu default:
188368c929daSCodrin Ciubotariu printf("%7d %11s\n", i, "-");
188468c929daSCodrin Ciubotariu }
188568c929daSCodrin Ciubotariu }
188668c929daSCodrin Ciubotariu }
188768c929daSCodrin Ciubotariu
188868c929daSCodrin Ciubotariu return CMD_RET_SUCCESS;
188968c929daSCodrin Ciubotariu }
189068c929daSCodrin Ciubotariu
vsc9953_learn_set_key_func(struct ethsw_command_def * parsed_cmd)189168c929daSCodrin Ciubotariu static int vsc9953_learn_set_key_func(struct ethsw_command_def *parsed_cmd)
189268c929daSCodrin Ciubotariu {
189368c929daSCodrin Ciubotariu int i;
189468c929daSCodrin Ciubotariu enum port_learn_mode mode;
189568c929daSCodrin Ciubotariu
189668c929daSCodrin Ciubotariu /* Last keyword should tell us the learn mode */
189768c929daSCodrin Ciubotariu if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
189868c929daSCodrin Ciubotariu ethsw_id_auto)
189968c929daSCodrin Ciubotariu mode = PORT_LEARN_AUTO;
190068c929daSCodrin Ciubotariu else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
190168c929daSCodrin Ciubotariu ethsw_id_disable)
190268c929daSCodrin Ciubotariu mode = PORT_LEARN_NONE;
190368c929daSCodrin Ciubotariu else
190468c929daSCodrin Ciubotariu return CMD_RET_USAGE;
190568c929daSCodrin Ciubotariu
190668c929daSCodrin Ciubotariu if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
190768c929daSCodrin Ciubotariu if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
190868c929daSCodrin Ciubotariu printf("Invalid port number: %d\n", parsed_cmd->port);
190968c929daSCodrin Ciubotariu return CMD_RET_FAILURE;
191068c929daSCodrin Ciubotariu }
191168c929daSCodrin Ciubotariu vsc9953_port_learn_mode_set(parsed_cmd->port, mode);
191268c929daSCodrin Ciubotariu } else {
191368c929daSCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++)
191468c929daSCodrin Ciubotariu vsc9953_port_learn_mode_set(i, mode);
191568c929daSCodrin Ciubotariu }
191668c929daSCodrin Ciubotariu
191768c929daSCodrin Ciubotariu return CMD_RET_SUCCESS;
191868c929daSCodrin Ciubotariu }
191968c929daSCodrin Ciubotariu
vsc9953_fdb_show_key_func(struct ethsw_command_def * parsed_cmd)192022449858SCodrin Ciubotariu static int vsc9953_fdb_show_key_func(struct ethsw_command_def *parsed_cmd)
192122449858SCodrin Ciubotariu {
192222449858SCodrin Ciubotariu if (parsed_cmd->port != ETHSW_CMD_PORT_ALL &&
192322449858SCodrin Ciubotariu !VSC9953_PORT_CHECK(parsed_cmd->port)) {
192422449858SCodrin Ciubotariu printf("Invalid port number: %d\n", parsed_cmd->port);
192522449858SCodrin Ciubotariu return CMD_RET_FAILURE;
192622449858SCodrin Ciubotariu }
192722449858SCodrin Ciubotariu
192822449858SCodrin Ciubotariu if (parsed_cmd->vid != ETHSW_CMD_VLAN_ALL &&
192922449858SCodrin Ciubotariu !VSC9953_VLAN_CHECK(parsed_cmd->vid)) {
193022449858SCodrin Ciubotariu printf("Invalid VID number: %d\n", parsed_cmd->vid);
193122449858SCodrin Ciubotariu return CMD_RET_FAILURE;
193222449858SCodrin Ciubotariu }
193322449858SCodrin Ciubotariu
193422449858SCodrin Ciubotariu vsc9953_mac_table_show(parsed_cmd->port, parsed_cmd->vid);
193522449858SCodrin Ciubotariu
193622449858SCodrin Ciubotariu return CMD_RET_SUCCESS;
193722449858SCodrin Ciubotariu }
193822449858SCodrin Ciubotariu
vsc9953_fdb_flush_key_func(struct ethsw_command_def * parsed_cmd)193922449858SCodrin Ciubotariu static int vsc9953_fdb_flush_key_func(struct ethsw_command_def *parsed_cmd)
194022449858SCodrin Ciubotariu {
194122449858SCodrin Ciubotariu if (parsed_cmd->port != ETHSW_CMD_PORT_ALL &&
194222449858SCodrin Ciubotariu !VSC9953_PORT_CHECK(parsed_cmd->port)) {
194322449858SCodrin Ciubotariu printf("Invalid port number: %d\n", parsed_cmd->port);
194422449858SCodrin Ciubotariu return CMD_RET_FAILURE;
194522449858SCodrin Ciubotariu }
194622449858SCodrin Ciubotariu
194722449858SCodrin Ciubotariu if (parsed_cmd->vid != ETHSW_CMD_VLAN_ALL &&
194822449858SCodrin Ciubotariu !VSC9953_VLAN_CHECK(parsed_cmd->vid)) {
194922449858SCodrin Ciubotariu printf("Invalid VID number: %d\n", parsed_cmd->vid);
195022449858SCodrin Ciubotariu return CMD_RET_FAILURE;
195122449858SCodrin Ciubotariu }
195222449858SCodrin Ciubotariu
195322449858SCodrin Ciubotariu vsc9953_mac_table_flush(parsed_cmd->port, parsed_cmd->vid);
195422449858SCodrin Ciubotariu
195522449858SCodrin Ciubotariu return CMD_RET_SUCCESS;
195622449858SCodrin Ciubotariu }
195722449858SCodrin Ciubotariu
vsc9953_fdb_entry_add_key_func(struct ethsw_command_def * parsed_cmd)195822449858SCodrin Ciubotariu static int vsc9953_fdb_entry_add_key_func(struct ethsw_command_def *parsed_cmd)
195922449858SCodrin Ciubotariu {
196022449858SCodrin Ciubotariu int vid;
196122449858SCodrin Ciubotariu
196222449858SCodrin Ciubotariu /* a port number must be present */
196322449858SCodrin Ciubotariu if (parsed_cmd->port == ETHSW_CMD_PORT_ALL) {
196422449858SCodrin Ciubotariu printf("Please specify a port\n");
196522449858SCodrin Ciubotariu return CMD_RET_FAILURE;
196622449858SCodrin Ciubotariu }
196722449858SCodrin Ciubotariu
196822449858SCodrin Ciubotariu if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
196922449858SCodrin Ciubotariu printf("Invalid port number: %d\n", parsed_cmd->port);
197022449858SCodrin Ciubotariu return CMD_RET_FAILURE;
197122449858SCodrin Ciubotariu }
197222449858SCodrin Ciubotariu
197322449858SCodrin Ciubotariu /* Use VLAN 1 if VID is not set */
197422449858SCodrin Ciubotariu vid = (parsed_cmd->vid == ETHSW_CMD_VLAN_ALL ? 1 : parsed_cmd->vid);
197522449858SCodrin Ciubotariu
197622449858SCodrin Ciubotariu if (!VSC9953_VLAN_CHECK(vid)) {
197722449858SCodrin Ciubotariu printf("Invalid VID number: %d\n", vid);
197822449858SCodrin Ciubotariu return CMD_RET_FAILURE;
197922449858SCodrin Ciubotariu }
198022449858SCodrin Ciubotariu
198122449858SCodrin Ciubotariu if (vsc9953_mac_table_add(parsed_cmd->port, parsed_cmd->ethaddr, vid))
198222449858SCodrin Ciubotariu return CMD_RET_FAILURE;
198322449858SCodrin Ciubotariu
198422449858SCodrin Ciubotariu return CMD_RET_SUCCESS;
198522449858SCodrin Ciubotariu }
198622449858SCodrin Ciubotariu
vsc9953_fdb_entry_del_key_func(struct ethsw_command_def * parsed_cmd)198722449858SCodrin Ciubotariu static int vsc9953_fdb_entry_del_key_func(struct ethsw_command_def *parsed_cmd)
198822449858SCodrin Ciubotariu {
198922449858SCodrin Ciubotariu int vid;
199022449858SCodrin Ciubotariu
199122449858SCodrin Ciubotariu /* Use VLAN 1 if VID is not set */
199222449858SCodrin Ciubotariu vid = (parsed_cmd->vid == ETHSW_CMD_VLAN_ALL ? 1 : parsed_cmd->vid);
199322449858SCodrin Ciubotariu
199422449858SCodrin Ciubotariu if (!VSC9953_VLAN_CHECK(vid)) {
199522449858SCodrin Ciubotariu printf("Invalid VID number: %d\n", vid);
199622449858SCodrin Ciubotariu return CMD_RET_FAILURE;
199722449858SCodrin Ciubotariu }
199822449858SCodrin Ciubotariu
199922449858SCodrin Ciubotariu if (vsc9953_mac_table_del(parsed_cmd->ethaddr, vid))
200022449858SCodrin Ciubotariu return CMD_RET_FAILURE;
200122449858SCodrin Ciubotariu
200222449858SCodrin Ciubotariu return CMD_RET_SUCCESS;
200322449858SCodrin Ciubotariu }
200422449858SCodrin Ciubotariu
vsc9953_pvid_show_key_func(struct ethsw_command_def * parsed_cmd)2005a2477924SCodrin Ciubotariu static int vsc9953_pvid_show_key_func(struct ethsw_command_def *parsed_cmd)
2006a2477924SCodrin Ciubotariu {
2007a2477924SCodrin Ciubotariu int i;
2008a2477924SCodrin Ciubotariu int pvid;
2009a2477924SCodrin Ciubotariu
2010a2477924SCodrin Ciubotariu if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
2011a2477924SCodrin Ciubotariu if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
2012a2477924SCodrin Ciubotariu printf("Invalid port number: %d\n", parsed_cmd->port);
2013a2477924SCodrin Ciubotariu return CMD_RET_FAILURE;
2014a2477924SCodrin Ciubotariu }
2015a2477924SCodrin Ciubotariu
2016a2477924SCodrin Ciubotariu if (vsc9953_port_vlan_pvid_get(parsed_cmd->port, &pvid))
2017a2477924SCodrin Ciubotariu return CMD_RET_FAILURE;
2018a2477924SCodrin Ciubotariu printf("%7s %7s\n", "Port", "PVID");
2019a2477924SCodrin Ciubotariu printf("%7d %7d\n", parsed_cmd->port, pvid);
2020a2477924SCodrin Ciubotariu } else {
2021a2477924SCodrin Ciubotariu printf("%7s %7s\n", "Port", "PVID");
2022a2477924SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++) {
2023a2477924SCodrin Ciubotariu if (vsc9953_port_vlan_pvid_get(i, &pvid))
2024a2477924SCodrin Ciubotariu continue;
2025a2477924SCodrin Ciubotariu printf("%7d %7d\n", i, pvid);
2026a2477924SCodrin Ciubotariu }
2027a2477924SCodrin Ciubotariu }
2028a2477924SCodrin Ciubotariu
2029a2477924SCodrin Ciubotariu return CMD_RET_SUCCESS;
2030a2477924SCodrin Ciubotariu }
2031a2477924SCodrin Ciubotariu
vsc9953_pvid_set_key_func(struct ethsw_command_def * parsed_cmd)2032a2477924SCodrin Ciubotariu static int vsc9953_pvid_set_key_func(struct ethsw_command_def *parsed_cmd)
2033a2477924SCodrin Ciubotariu {
2034a2477924SCodrin Ciubotariu /* PVID number should be set in parsed_cmd->vid */
2035a2477924SCodrin Ciubotariu if (parsed_cmd->vid == ETHSW_CMD_VLAN_ALL) {
2036a2477924SCodrin Ciubotariu printf("Please set a pvid value\n");
2037a2477924SCodrin Ciubotariu return CMD_RET_FAILURE;
2038a2477924SCodrin Ciubotariu }
2039a2477924SCodrin Ciubotariu
2040a2477924SCodrin Ciubotariu if (!VSC9953_VLAN_CHECK(parsed_cmd->vid)) {
2041a2477924SCodrin Ciubotariu printf("Invalid VID number: %d\n", parsed_cmd->vid);
2042a2477924SCodrin Ciubotariu return CMD_RET_FAILURE;
2043a2477924SCodrin Ciubotariu }
2044a2477924SCodrin Ciubotariu
2045a2477924SCodrin Ciubotariu if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
2046a2477924SCodrin Ciubotariu if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
2047a2477924SCodrin Ciubotariu printf("Invalid port number: %d\n", parsed_cmd->port);
2048a2477924SCodrin Ciubotariu return CMD_RET_FAILURE;
2049a2477924SCodrin Ciubotariu }
2050a2477924SCodrin Ciubotariu vsc9953_port_vlan_pvid_set(parsed_cmd->port, parsed_cmd->vid);
2051a2477924SCodrin Ciubotariu } else {
2052a2477924SCodrin Ciubotariu vsc9953_port_all_vlan_pvid_set(parsed_cmd->vid);
2053a2477924SCodrin Ciubotariu }
2054a2477924SCodrin Ciubotariu
2055a2477924SCodrin Ciubotariu return CMD_RET_SUCCESS;
2056a2477924SCodrin Ciubotariu }
2057a2477924SCodrin Ciubotariu
vsc9953_vlan_show_key_func(struct ethsw_command_def * parsed_cmd)2058a2477924SCodrin Ciubotariu static int vsc9953_vlan_show_key_func(struct ethsw_command_def *parsed_cmd)
2059a2477924SCodrin Ciubotariu {
2060a2477924SCodrin Ciubotariu int i;
2061a2477924SCodrin Ciubotariu
2062a2477924SCodrin Ciubotariu if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
2063a2477924SCodrin Ciubotariu if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
2064a2477924SCodrin Ciubotariu printf("Invalid port number: %d\n", parsed_cmd->port);
2065a2477924SCodrin Ciubotariu return CMD_RET_FAILURE;
2066a2477924SCodrin Ciubotariu }
2067a2477924SCodrin Ciubotariu vsc9953_vlan_membership_show(parsed_cmd->port);
2068a2477924SCodrin Ciubotariu } else {
2069a2477924SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++)
2070a2477924SCodrin Ciubotariu vsc9953_vlan_membership_show(i);
2071a2477924SCodrin Ciubotariu }
2072a2477924SCodrin Ciubotariu
2073a2477924SCodrin Ciubotariu return CMD_RET_SUCCESS;
2074a2477924SCodrin Ciubotariu }
2075a2477924SCodrin Ciubotariu
vsc9953_vlan_set_key_func(struct ethsw_command_def * parsed_cmd)2076a2477924SCodrin Ciubotariu static int vsc9953_vlan_set_key_func(struct ethsw_command_def *parsed_cmd)
2077a2477924SCodrin Ciubotariu {
2078a2477924SCodrin Ciubotariu int i;
2079a2477924SCodrin Ciubotariu int add;
2080a2477924SCodrin Ciubotariu
2081a2477924SCodrin Ciubotariu /* VLAN should be set in parsed_cmd->vid */
2082a2477924SCodrin Ciubotariu if (parsed_cmd->vid == ETHSW_CMD_VLAN_ALL) {
2083a2477924SCodrin Ciubotariu printf("Please set a vlan value\n");
2084a2477924SCodrin Ciubotariu return CMD_RET_FAILURE;
2085a2477924SCodrin Ciubotariu }
2086a2477924SCodrin Ciubotariu
2087a2477924SCodrin Ciubotariu if (!VSC9953_VLAN_CHECK(parsed_cmd->vid)) {
2088a2477924SCodrin Ciubotariu printf("Invalid VID number: %d\n", parsed_cmd->vid);
2089a2477924SCodrin Ciubotariu return CMD_RET_FAILURE;
2090a2477924SCodrin Ciubotariu }
2091a2477924SCodrin Ciubotariu
2092a2477924SCodrin Ciubotariu /* keywords add/delete should be the last but one in array */
2093a2477924SCodrin Ciubotariu if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 2] ==
2094a2477924SCodrin Ciubotariu ethsw_id_add)
2095a2477924SCodrin Ciubotariu add = 1;
2096a2477924SCodrin Ciubotariu else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 2] ==
2097a2477924SCodrin Ciubotariu ethsw_id_del)
2098a2477924SCodrin Ciubotariu add = 0;
2099a2477924SCodrin Ciubotariu else
2100a2477924SCodrin Ciubotariu return CMD_RET_USAGE;
2101a2477924SCodrin Ciubotariu
2102a2477924SCodrin Ciubotariu if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
2103a2477924SCodrin Ciubotariu if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
2104a2477924SCodrin Ciubotariu printf("Invalid port number: %d\n", parsed_cmd->port);
2105a2477924SCodrin Ciubotariu return CMD_RET_FAILURE;
2106a2477924SCodrin Ciubotariu }
2107a2477924SCodrin Ciubotariu vsc9953_vlan_table_membership_set(parsed_cmd->vid,
2108a2477924SCodrin Ciubotariu parsed_cmd->port, add);
2109a2477924SCodrin Ciubotariu } else {
2110a2477924SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++)
2111a2477924SCodrin Ciubotariu vsc9953_vlan_table_membership_set(parsed_cmd->vid, i,
2112a2477924SCodrin Ciubotariu add);
2113a2477924SCodrin Ciubotariu }
2114a2477924SCodrin Ciubotariu
2115a2477924SCodrin Ciubotariu return CMD_RET_SUCCESS;
2116a2477924SCodrin Ciubotariu }
vsc9953_port_untag_show_key_func(struct ethsw_command_def * parsed_cmd)2117a2477924SCodrin Ciubotariu static int vsc9953_port_untag_show_key_func(
2118a2477924SCodrin Ciubotariu struct ethsw_command_def *parsed_cmd)
2119a2477924SCodrin Ciubotariu {
2120a2477924SCodrin Ciubotariu int i;
2121a2477924SCodrin Ciubotariu
2122a2477924SCodrin Ciubotariu printf("%7s\t%17s\n", "Port", "Untag");
2123a2477924SCodrin Ciubotariu if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
2124a2477924SCodrin Ciubotariu if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
2125a2477924SCodrin Ciubotariu printf("Invalid port number: %d\n", parsed_cmd->port);
2126a2477924SCodrin Ciubotariu return CMD_RET_FAILURE;
2127a2477924SCodrin Ciubotariu }
2128a2477924SCodrin Ciubotariu vsc9953_port_vlan_egr_untag_show(parsed_cmd->port);
2129a2477924SCodrin Ciubotariu } else {
2130a2477924SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++)
2131a2477924SCodrin Ciubotariu vsc9953_port_vlan_egr_untag_show(i);
2132a2477924SCodrin Ciubotariu }
2133a2477924SCodrin Ciubotariu
2134a2477924SCodrin Ciubotariu return CMD_RET_SUCCESS;
2135a2477924SCodrin Ciubotariu }
2136a2477924SCodrin Ciubotariu
vsc9953_port_untag_set_key_func(struct ethsw_command_def * parsed_cmd)2137a2477924SCodrin Ciubotariu static int vsc9953_port_untag_set_key_func(struct ethsw_command_def *parsed_cmd)
2138a2477924SCodrin Ciubotariu {
2139a2477924SCodrin Ciubotariu int i;
2140a2477924SCodrin Ciubotariu enum egress_untag_mode mode;
2141a2477924SCodrin Ciubotariu
2142a2477924SCodrin Ciubotariu /* keywords for the untagged mode are the last in the array */
2143a2477924SCodrin Ciubotariu if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
2144a2477924SCodrin Ciubotariu ethsw_id_all)
2145a2477924SCodrin Ciubotariu mode = EGRESS_UNTAG_ALL;
2146a2477924SCodrin Ciubotariu else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
2147a2477924SCodrin Ciubotariu ethsw_id_none)
2148a2477924SCodrin Ciubotariu mode = EGRESS_UNTAG_NONE;
2149a2477924SCodrin Ciubotariu else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
2150a2477924SCodrin Ciubotariu ethsw_id_pvid)
2151a2477924SCodrin Ciubotariu mode = EGRESS_UNTAG_PVID_AND_ZERO;
2152a2477924SCodrin Ciubotariu else
2153a2477924SCodrin Ciubotariu return CMD_RET_USAGE;
2154a2477924SCodrin Ciubotariu
2155a2477924SCodrin Ciubotariu if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
2156a2477924SCodrin Ciubotariu if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
2157a2477924SCodrin Ciubotariu printf("Invalid port number: %d\n", parsed_cmd->port);
2158a2477924SCodrin Ciubotariu return CMD_RET_FAILURE;
2159a2477924SCodrin Ciubotariu }
2160a2477924SCodrin Ciubotariu vsc9953_port_vlan_egr_untag_set(parsed_cmd->port, mode);
2161a2477924SCodrin Ciubotariu } else {
2162a2477924SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++)
2163a2477924SCodrin Ciubotariu vsc9953_port_vlan_egr_untag_set(i, mode);
2164a2477924SCodrin Ciubotariu }
2165a2477924SCodrin Ciubotariu
2166a2477924SCodrin Ciubotariu return CMD_RET_SUCCESS;
2167a2477924SCodrin Ciubotariu }
2168a2477924SCodrin Ciubotariu
vsc9953_egr_vlan_tag_show_key_func(struct ethsw_command_def * parsed_cmd)2169a2477924SCodrin Ciubotariu static int vsc9953_egr_vlan_tag_show_key_func(
2170a2477924SCodrin Ciubotariu struct ethsw_command_def *parsed_cmd)
2171a2477924SCodrin Ciubotariu {
2172a2477924SCodrin Ciubotariu int i;
2173a2477924SCodrin Ciubotariu enum egress_vlan_tag mode;
2174a2477924SCodrin Ciubotariu
2175a2477924SCodrin Ciubotariu if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
2176a2477924SCodrin Ciubotariu if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
2177a2477924SCodrin Ciubotariu printf("Invalid port number: %d\n", parsed_cmd->port);
2178a2477924SCodrin Ciubotariu return CMD_RET_FAILURE;
2179a2477924SCodrin Ciubotariu }
2180a2477924SCodrin Ciubotariu vsc9953_port_vlan_egress_tag_get(parsed_cmd->port, &mode);
2181a2477924SCodrin Ciubotariu printf("%7s\t%12s\n", "Port", "Egress VID");
2182a2477924SCodrin Ciubotariu printf("%7d\t", parsed_cmd->port);
2183a2477924SCodrin Ciubotariu switch (mode) {
2184a2477924SCodrin Ciubotariu case EGR_TAG_CLASS:
2185a2477924SCodrin Ciubotariu printf("%12s\n", "classified");
2186a2477924SCodrin Ciubotariu break;
2187a2477924SCodrin Ciubotariu case EGR_TAG_PVID:
2188a2477924SCodrin Ciubotariu printf("%12s\n", "pvid");
2189a2477924SCodrin Ciubotariu break;
2190a2477924SCodrin Ciubotariu default:
2191a2477924SCodrin Ciubotariu printf("%12s\n", "-");
2192a2477924SCodrin Ciubotariu }
2193a2477924SCodrin Ciubotariu } else {
2194a2477924SCodrin Ciubotariu printf("%7s\t%12s\n", "Port", "Egress VID");
2195a2477924SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++) {
2196a2477924SCodrin Ciubotariu vsc9953_port_vlan_egress_tag_get(i, &mode);
2197a2477924SCodrin Ciubotariu switch (mode) {
2198a2477924SCodrin Ciubotariu case EGR_TAG_CLASS:
2199a2477924SCodrin Ciubotariu printf("%7d\t%12s\n", i, "classified");
2200a2477924SCodrin Ciubotariu break;
2201a2477924SCodrin Ciubotariu case EGR_TAG_PVID:
2202a2477924SCodrin Ciubotariu printf("%7d\t%12s\n", i, "pvid");
2203a2477924SCodrin Ciubotariu break;
2204a2477924SCodrin Ciubotariu default:
2205a2477924SCodrin Ciubotariu printf("%7d\t%12s\n", i, "-");
2206a2477924SCodrin Ciubotariu }
2207a2477924SCodrin Ciubotariu }
2208a2477924SCodrin Ciubotariu }
2209a2477924SCodrin Ciubotariu
2210a2477924SCodrin Ciubotariu return CMD_RET_SUCCESS;
2211a2477924SCodrin Ciubotariu }
2212a2477924SCodrin Ciubotariu
vsc9953_egr_vlan_tag_set_key_func(struct ethsw_command_def * parsed_cmd)2213a2477924SCodrin Ciubotariu static int vsc9953_egr_vlan_tag_set_key_func(
2214a2477924SCodrin Ciubotariu struct ethsw_command_def *parsed_cmd)
2215a2477924SCodrin Ciubotariu {
2216a2477924SCodrin Ciubotariu int i;
2217a2477924SCodrin Ciubotariu enum egress_vlan_tag mode;
2218a2477924SCodrin Ciubotariu
2219a2477924SCodrin Ciubotariu /* keywords for the egress vlan tag mode are the last in the array */
2220a2477924SCodrin Ciubotariu if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
2221a2477924SCodrin Ciubotariu ethsw_id_pvid)
2222a2477924SCodrin Ciubotariu mode = EGR_TAG_PVID;
2223a2477924SCodrin Ciubotariu else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
2224a2477924SCodrin Ciubotariu ethsw_id_classified)
2225a2477924SCodrin Ciubotariu mode = EGR_TAG_CLASS;
2226a2477924SCodrin Ciubotariu else
2227a2477924SCodrin Ciubotariu return CMD_RET_USAGE;
2228a2477924SCodrin Ciubotariu
2229a2477924SCodrin Ciubotariu if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
2230a2477924SCodrin Ciubotariu if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
2231a2477924SCodrin Ciubotariu printf("Invalid port number: %d\n", parsed_cmd->port);
2232a2477924SCodrin Ciubotariu return CMD_RET_FAILURE;
2233a2477924SCodrin Ciubotariu }
2234a2477924SCodrin Ciubotariu vsc9953_port_vlan_egress_tag_set(parsed_cmd->port, mode);
2235a2477924SCodrin Ciubotariu } else {
2236a2477924SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++)
2237a2477924SCodrin Ciubotariu vsc9953_port_vlan_egress_tag_set(i, mode);
2238a2477924SCodrin Ciubotariu }
2239a2477924SCodrin Ciubotariu
2240a2477924SCodrin Ciubotariu return CMD_RET_SUCCESS;
2241a2477924SCodrin Ciubotariu }
2242a2477924SCodrin Ciubotariu
vsc9953_vlan_learn_show_key_func(struct ethsw_command_def * parsed_cmd)224321d214fcSCodrin Ciubotariu static int vsc9953_vlan_learn_show_key_func(
224421d214fcSCodrin Ciubotariu struct ethsw_command_def *parsed_cmd)
224521d214fcSCodrin Ciubotariu {
224621d214fcSCodrin Ciubotariu int rc;
224721d214fcSCodrin Ciubotariu enum vlan_learning_mode mode;
224821d214fcSCodrin Ciubotariu
224921d214fcSCodrin Ciubotariu rc = vsc9953_vlan_learning_get(&mode);
225021d214fcSCodrin Ciubotariu if (rc)
225121d214fcSCodrin Ciubotariu return CMD_RET_FAILURE;
225221d214fcSCodrin Ciubotariu
225321d214fcSCodrin Ciubotariu switch (mode) {
225421d214fcSCodrin Ciubotariu case SHARED_VLAN_LEARNING:
225521d214fcSCodrin Ciubotariu printf("VLAN learning mode: shared\n");
225621d214fcSCodrin Ciubotariu break;
225721d214fcSCodrin Ciubotariu case PRIVATE_VLAN_LEARNING:
225821d214fcSCodrin Ciubotariu printf("VLAN learning mode: private\n");
225921d214fcSCodrin Ciubotariu break;
226021d214fcSCodrin Ciubotariu default:
226121d214fcSCodrin Ciubotariu printf("Unknown VLAN learning mode\n");
226221d214fcSCodrin Ciubotariu rc = CMD_RET_FAILURE;
226321d214fcSCodrin Ciubotariu }
226421d214fcSCodrin Ciubotariu
226521d214fcSCodrin Ciubotariu return CMD_RET_SUCCESS;
226621d214fcSCodrin Ciubotariu }
226721d214fcSCodrin Ciubotariu
vsc9953_vlan_learn_set_key_func(struct ethsw_command_def * parsed_cmd)226821d214fcSCodrin Ciubotariu static int vsc9953_vlan_learn_set_key_func(struct ethsw_command_def *parsed_cmd)
226921d214fcSCodrin Ciubotariu {
227021d214fcSCodrin Ciubotariu enum vlan_learning_mode mode;
227121d214fcSCodrin Ciubotariu
227221d214fcSCodrin Ciubotariu /* keywords for shared/private are the last in the array */
227321d214fcSCodrin Ciubotariu if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
227421d214fcSCodrin Ciubotariu ethsw_id_shared)
227521d214fcSCodrin Ciubotariu mode = SHARED_VLAN_LEARNING;
227621d214fcSCodrin Ciubotariu else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
227721d214fcSCodrin Ciubotariu ethsw_id_private)
227821d214fcSCodrin Ciubotariu mode = PRIVATE_VLAN_LEARNING;
227921d214fcSCodrin Ciubotariu else
228021d214fcSCodrin Ciubotariu return CMD_RET_USAGE;
228121d214fcSCodrin Ciubotariu
228221d214fcSCodrin Ciubotariu vsc9953_vlan_learning_set(mode);
228321d214fcSCodrin Ciubotariu
228421d214fcSCodrin Ciubotariu return CMD_RET_SUCCESS;
228521d214fcSCodrin Ciubotariu }
228621d214fcSCodrin Ciubotariu
vsc9953_ingr_fltr_show_key_func(struct ethsw_command_def * parsed_cmd)22875ed1bacdSCodrin Ciubotariu static int vsc9953_ingr_fltr_show_key_func(struct ethsw_command_def *parsed_cmd)
22885ed1bacdSCodrin Ciubotariu {
22895ed1bacdSCodrin Ciubotariu int i;
22905ed1bacdSCodrin Ciubotariu int enabled;
22915ed1bacdSCodrin Ciubotariu
22925ed1bacdSCodrin Ciubotariu printf("%7s\t%18s\n", "Port", "Ingress filtering");
22935ed1bacdSCodrin Ciubotariu if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
22945ed1bacdSCodrin Ciubotariu if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
22955ed1bacdSCodrin Ciubotariu printf("Invalid port number: %d\n", parsed_cmd->port);
22965ed1bacdSCodrin Ciubotariu return CMD_RET_FAILURE;
22975ed1bacdSCodrin Ciubotariu }
22985ed1bacdSCodrin Ciubotariu enabled = vsc9953_port_ingress_filtering_get(parsed_cmd->port);
22995ed1bacdSCodrin Ciubotariu printf("%7d\t%18s\n", parsed_cmd->port, enabled ? "enable" :
23005ed1bacdSCodrin Ciubotariu "disable");
23015ed1bacdSCodrin Ciubotariu } else {
23025ed1bacdSCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++) {
23035ed1bacdSCodrin Ciubotariu enabled = vsc9953_port_ingress_filtering_get(i);
23045ed1bacdSCodrin Ciubotariu printf("%7d\t%18s\n", parsed_cmd->port, enabled ?
23055ed1bacdSCodrin Ciubotariu "enable" :
23065ed1bacdSCodrin Ciubotariu "disable");
23075ed1bacdSCodrin Ciubotariu }
23085ed1bacdSCodrin Ciubotariu }
23095ed1bacdSCodrin Ciubotariu
23105ed1bacdSCodrin Ciubotariu return CMD_RET_SUCCESS;
23115ed1bacdSCodrin Ciubotariu }
23125ed1bacdSCodrin Ciubotariu
vsc9953_ingr_fltr_set_key_func(struct ethsw_command_def * parsed_cmd)23135ed1bacdSCodrin Ciubotariu static int vsc9953_ingr_fltr_set_key_func(struct ethsw_command_def *parsed_cmd)
23145ed1bacdSCodrin Ciubotariu {
23155ed1bacdSCodrin Ciubotariu int i;
23165ed1bacdSCodrin Ciubotariu int enable;
23175ed1bacdSCodrin Ciubotariu
23185ed1bacdSCodrin Ciubotariu /* keywords for enabling/disabling ingress filtering
23195ed1bacdSCodrin Ciubotariu * are the last in the array
23205ed1bacdSCodrin Ciubotariu */
23215ed1bacdSCodrin Ciubotariu if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
23225ed1bacdSCodrin Ciubotariu ethsw_id_enable)
23235ed1bacdSCodrin Ciubotariu enable = 1;
23245ed1bacdSCodrin Ciubotariu else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
23255ed1bacdSCodrin Ciubotariu ethsw_id_disable)
23265ed1bacdSCodrin Ciubotariu enable = 0;
23275ed1bacdSCodrin Ciubotariu else
23285ed1bacdSCodrin Ciubotariu return CMD_RET_USAGE;
23295ed1bacdSCodrin Ciubotariu
23305ed1bacdSCodrin Ciubotariu if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
23315ed1bacdSCodrin Ciubotariu if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
23325ed1bacdSCodrin Ciubotariu printf("Invalid port number: %d\n", parsed_cmd->port);
23335ed1bacdSCodrin Ciubotariu return CMD_RET_FAILURE;
23345ed1bacdSCodrin Ciubotariu }
23355ed1bacdSCodrin Ciubotariu vsc9953_port_ingress_filtering_set(parsed_cmd->port, enable);
23365ed1bacdSCodrin Ciubotariu } else {
23375ed1bacdSCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++)
23385ed1bacdSCodrin Ciubotariu vsc9953_port_ingress_filtering_set(i, enable);
23395ed1bacdSCodrin Ciubotariu }
23405ed1bacdSCodrin Ciubotariu
23415ed1bacdSCodrin Ciubotariu return CMD_RET_SUCCESS;
23425ed1bacdSCodrin Ciubotariu }
23435ed1bacdSCodrin Ciubotariu
vsc9953_port_aggr_show_key_func(struct ethsw_command_def * parsed_cmd)2344aae0e689SCodrin Ciubotariu static int vsc9953_port_aggr_show_key_func(struct ethsw_command_def *parsed_cmd)
2345aae0e689SCodrin Ciubotariu {
2346aae0e689SCodrin Ciubotariu int i;
2347aae0e689SCodrin Ciubotariu int aggr_grp;
2348aae0e689SCodrin Ciubotariu
2349aae0e689SCodrin Ciubotariu if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
2350aae0e689SCodrin Ciubotariu if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
2351aae0e689SCodrin Ciubotariu printf("Invalid port number: %d\n", parsed_cmd->port);
2352aae0e689SCodrin Ciubotariu return CMD_RET_FAILURE;
2353aae0e689SCodrin Ciubotariu }
2354aae0e689SCodrin Ciubotariu
2355aae0e689SCodrin Ciubotariu if (vsc9953_port_aggr_grp_get(parsed_cmd->port, &aggr_grp))
2356aae0e689SCodrin Ciubotariu return CMD_RET_FAILURE;
2357aae0e689SCodrin Ciubotariu printf("%7s %10s\n", "Port", "Aggr grp");
2358aae0e689SCodrin Ciubotariu printf("%7d %10d\n", parsed_cmd->port, aggr_grp);
2359aae0e689SCodrin Ciubotariu } else {
2360aae0e689SCodrin Ciubotariu printf("%7s %10s\n", "Port", "Aggr grp");
2361aae0e689SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++) {
2362aae0e689SCodrin Ciubotariu if (vsc9953_port_aggr_grp_get(i, &aggr_grp))
2363aae0e689SCodrin Ciubotariu continue;
2364aae0e689SCodrin Ciubotariu printf("%7d %10d\n", i, aggr_grp);
2365aae0e689SCodrin Ciubotariu }
2366aae0e689SCodrin Ciubotariu }
2367aae0e689SCodrin Ciubotariu
2368aae0e689SCodrin Ciubotariu return CMD_RET_SUCCESS;
2369aae0e689SCodrin Ciubotariu }
2370aae0e689SCodrin Ciubotariu
vsc9953_port_aggr_set_key_func(struct ethsw_command_def * parsed_cmd)2371aae0e689SCodrin Ciubotariu static int vsc9953_port_aggr_set_key_func(struct ethsw_command_def *parsed_cmd)
2372aae0e689SCodrin Ciubotariu {
2373aae0e689SCodrin Ciubotariu int i;
2374aae0e689SCodrin Ciubotariu
2375aae0e689SCodrin Ciubotariu /* Aggregation group number should be set in parsed_cmd->aggr_grp */
2376aae0e689SCodrin Ciubotariu if (parsed_cmd->aggr_grp == ETHSW_CMD_AGGR_GRP_NONE) {
2377aae0e689SCodrin Ciubotariu printf("Please set an aggregation group value\n");
2378aae0e689SCodrin Ciubotariu return CMD_RET_FAILURE;
2379aae0e689SCodrin Ciubotariu }
2380aae0e689SCodrin Ciubotariu
2381aae0e689SCodrin Ciubotariu if (!VSC9953_PORT_CHECK(parsed_cmd->aggr_grp)) {
2382aae0e689SCodrin Ciubotariu printf("Invalid aggregation group number: %d\n",
2383aae0e689SCodrin Ciubotariu parsed_cmd->aggr_grp);
2384aae0e689SCodrin Ciubotariu return CMD_RET_FAILURE;
2385aae0e689SCodrin Ciubotariu }
2386aae0e689SCodrin Ciubotariu
2387aae0e689SCodrin Ciubotariu if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
2388aae0e689SCodrin Ciubotariu if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
2389aae0e689SCodrin Ciubotariu printf("Invalid port number: %d\n", parsed_cmd->port);
2390aae0e689SCodrin Ciubotariu return CMD_RET_FAILURE;
2391aae0e689SCodrin Ciubotariu }
2392aae0e689SCodrin Ciubotariu if (vsc9953_port_aggr_grp_set(parsed_cmd->port,
2393aae0e689SCodrin Ciubotariu parsed_cmd->aggr_grp)) {
2394aae0e689SCodrin Ciubotariu printf("Port %d: failed to set aggr group %d\n",
2395aae0e689SCodrin Ciubotariu parsed_cmd->port, parsed_cmd->aggr_grp);
2396aae0e689SCodrin Ciubotariu }
2397aae0e689SCodrin Ciubotariu } else {
2398aae0e689SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++) {
2399aae0e689SCodrin Ciubotariu if (vsc9953_port_aggr_grp_set(i,
2400aae0e689SCodrin Ciubotariu parsed_cmd->aggr_grp)) {
2401aae0e689SCodrin Ciubotariu printf("Port %d: failed to set aggr group %d\n",
2402aae0e689SCodrin Ciubotariu i, parsed_cmd->aggr_grp);
2403aae0e689SCodrin Ciubotariu }
2404aae0e689SCodrin Ciubotariu }
2405aae0e689SCodrin Ciubotariu }
2406aae0e689SCodrin Ciubotariu
2407aae0e689SCodrin Ciubotariu return CMD_RET_SUCCESS;
2408aae0e689SCodrin Ciubotariu }
2409aae0e689SCodrin Ciubotariu
241024a23debSCodrin Ciubotariu static struct ethsw_command_func vsc9953_cmd_func = {
241124a23debSCodrin Ciubotariu .ethsw_name = "L2 Switch VSC9953",
241224a23debSCodrin Ciubotariu .port_enable = &vsc9953_port_status_key_func,
241324a23debSCodrin Ciubotariu .port_disable = &vsc9953_port_status_key_func,
241424a23debSCodrin Ciubotariu .port_show = &vsc9953_port_config_key_func,
241586719f0cSCodrin Ciubotariu .port_stats = &vsc9953_port_stats_key_func,
241686719f0cSCodrin Ciubotariu .port_stats_clear = &vsc9953_port_stats_clear_key_func,
241768c929daSCodrin Ciubotariu .port_learn = &vsc9953_learn_set_key_func,
241868c929daSCodrin Ciubotariu .port_learn_show = &vsc9953_learn_show_key_func,
241922449858SCodrin Ciubotariu .fdb_show = &vsc9953_fdb_show_key_func,
242022449858SCodrin Ciubotariu .fdb_flush = &vsc9953_fdb_flush_key_func,
242122449858SCodrin Ciubotariu .fdb_entry_add = &vsc9953_fdb_entry_add_key_func,
242222449858SCodrin Ciubotariu .fdb_entry_del = &vsc9953_fdb_entry_del_key_func,
2423a2477924SCodrin Ciubotariu .pvid_show = &vsc9953_pvid_show_key_func,
2424a2477924SCodrin Ciubotariu .pvid_set = &vsc9953_pvid_set_key_func,
2425a2477924SCodrin Ciubotariu .vlan_show = &vsc9953_vlan_show_key_func,
2426a2477924SCodrin Ciubotariu .vlan_set = &vsc9953_vlan_set_key_func,
2427a2477924SCodrin Ciubotariu .port_untag_show = &vsc9953_port_untag_show_key_func,
2428a2477924SCodrin Ciubotariu .port_untag_set = &vsc9953_port_untag_set_key_func,
2429a2477924SCodrin Ciubotariu .port_egr_vlan_show = &vsc9953_egr_vlan_tag_show_key_func,
2430a2477924SCodrin Ciubotariu .port_egr_vlan_set = &vsc9953_egr_vlan_tag_set_key_func,
243121d214fcSCodrin Ciubotariu .vlan_learn_show = &vsc9953_vlan_learn_show_key_func,
243221d214fcSCodrin Ciubotariu .vlan_learn_set = &vsc9953_vlan_learn_set_key_func,
24335ed1bacdSCodrin Ciubotariu .port_ingr_filt_show = &vsc9953_ingr_fltr_show_key_func,
2434aae0e689SCodrin Ciubotariu .port_ingr_filt_set = &vsc9953_ingr_fltr_set_key_func,
2435aae0e689SCodrin Ciubotariu .port_aggr_show = &vsc9953_port_aggr_show_key_func,
2436aae0e689SCodrin Ciubotariu .port_aggr_set = &vsc9953_port_aggr_set_key_func,
243724a23debSCodrin Ciubotariu };
243824a23debSCodrin Ciubotariu
243924a23debSCodrin Ciubotariu #endif /* CONFIG_CMD_ETHSW */
244024a23debSCodrin Ciubotariu
24419de05987SCodrin Ciubotariu /*****************************************************************************
24429de05987SCodrin Ciubotariu At startup, the default configuration would be:
24439de05987SCodrin Ciubotariu - HW learning enabled on all ports; (HW default)
24449de05987SCodrin Ciubotariu - All ports are in VLAN 1;
24459de05987SCodrin Ciubotariu - All ports are VLAN aware;
24469de05987SCodrin Ciubotariu - All ports have POP_COUNT 1;
24479de05987SCodrin Ciubotariu - All ports have PVID 1;
24489de05987SCodrin Ciubotariu - All ports have TPID 0x8100; (HW default)
24499de05987SCodrin Ciubotariu - All ports tag frames classified to all VLANs that are not PVID;
24509de05987SCodrin Ciubotariu *****************************************************************************/
vsc9953_default_configuration(void)24519de05987SCodrin Ciubotariu void vsc9953_default_configuration(void)
24529de05987SCodrin Ciubotariu {
24539de05987SCodrin Ciubotariu int i;
24549de05987SCodrin Ciubotariu
2455ba389e65SCodrin Ciubotariu if (vsc9953_autoage_time_set(VSC9953_DEFAULT_AGE_TIME))
2456ba389e65SCodrin Ciubotariu debug("VSC9953: failed to set AGE time to %d\n",
2457ba389e65SCodrin Ciubotariu VSC9953_DEFAULT_AGE_TIME);
2458ba389e65SCodrin Ciubotariu
24599de05987SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_VLAN; i++)
24609de05987SCodrin Ciubotariu vsc9953_vlan_table_membership_all_set(i, 0);
24619de05987SCodrin Ciubotariu vsc9953_port_all_vlan_aware_set(1);
24629de05987SCodrin Ciubotariu vsc9953_port_all_vlan_pvid_set(1);
24639de05987SCodrin Ciubotariu vsc9953_port_all_vlan_poncnt_set(1);
24649de05987SCodrin Ciubotariu vsc9953_vlan_table_membership_all_set(1, 1);
24659de05987SCodrin Ciubotariu vsc9953_vlan_ingr_fltr_learn_drop(1);
24669de05987SCodrin Ciubotariu vsc9953_port_all_vlan_egress_untagged_set(EGRESS_UNTAG_PVID_AND_ZERO);
2467aae0e689SCodrin Ciubotariu if (vsc9953_aggr_code_set(AGGR_CODE_ALL))
2468aae0e689SCodrin Ciubotariu debug("VSC9953: failed to set default aggregation code mode\n");
24699de05987SCodrin Ciubotariu }
24709de05987SCodrin Ciubotariu
vcap_entry2cache_init(u32 target,u32 entry_words)2471*98017a1fSRadu Bulie static void vcap_entry2cache_init(u32 target, u32 entry_words)
2472*98017a1fSRadu Bulie {
2473*98017a1fSRadu Bulie int i;
2474*98017a1fSRadu Bulie
2475*98017a1fSRadu Bulie for (i = 0; i < entry_words; i++) {
2476*98017a1fSRadu Bulie out_le32((unsigned int *)(VSC9953_OFFSET +
2477*98017a1fSRadu Bulie VSC9953_VCAP_CACHE_ENTRY_DAT(target, i)), 0x00);
2478*98017a1fSRadu Bulie out_le32((unsigned int *)(VSC9953_OFFSET +
2479*98017a1fSRadu Bulie VSC9953_VCAP_CACHE_MASK_DAT(target, i)), 0xFF);
2480*98017a1fSRadu Bulie }
2481*98017a1fSRadu Bulie
2482*98017a1fSRadu Bulie out_le32((unsigned int *)(VSC9953_OFFSET +
2483*98017a1fSRadu Bulie VSC9953_VCAP_CACHE_TG_DAT(target)), 0x00);
2484*98017a1fSRadu Bulie out_le32((unsigned int *)(VSC9953_OFFSET +
2485*98017a1fSRadu Bulie VSC9953_VCAP_CFG_MV_CFG(target)),
2486*98017a1fSRadu Bulie VSC9953_VCAP_CFG_MV_CFG_SIZE(entry_words));
2487*98017a1fSRadu Bulie }
2488*98017a1fSRadu Bulie
vcap_action2cache_init(u32 target,u32 action_words,u32 counter_words)2489*98017a1fSRadu Bulie static void vcap_action2cache_init(u32 target, u32 action_words,
2490*98017a1fSRadu Bulie u32 counter_words)
2491*98017a1fSRadu Bulie {
2492*98017a1fSRadu Bulie int i;
2493*98017a1fSRadu Bulie
2494*98017a1fSRadu Bulie for (i = 0; i < action_words; i++)
2495*98017a1fSRadu Bulie out_le32((unsigned int *)(VSC9953_OFFSET +
2496*98017a1fSRadu Bulie VSC9953_VCAP_CACHE_ACTION_DAT(target, i)), 0x00);
2497*98017a1fSRadu Bulie
2498*98017a1fSRadu Bulie for (i = 0; i < counter_words; i++)
2499*98017a1fSRadu Bulie out_le32((unsigned int *)(VSC9953_OFFSET +
2500*98017a1fSRadu Bulie VSC9953_VCAP_CACHE_CNT_DAT(target, i)), 0x00);
2501*98017a1fSRadu Bulie }
2502*98017a1fSRadu Bulie
vcap_cmd(u32 target,u16 ix,int cmd,int sel,int entry_count)2503*98017a1fSRadu Bulie static int vcap_cmd(u32 target, u16 ix, int cmd, int sel, int entry_count)
2504*98017a1fSRadu Bulie {
2505*98017a1fSRadu Bulie u32 tgt = target;
2506*98017a1fSRadu Bulie u32 value = (VSC9953_VCAP_UPDATE_CTRL_UPDATE_CMD(cmd) |
2507*98017a1fSRadu Bulie VSC9953_VCAP_UPDATE_CTRL_UPDATE_ADDR(ix) |
2508*98017a1fSRadu Bulie VSC9953_VCAP_UPDATE_CTRL_UPDATE_SHOT);
2509*98017a1fSRadu Bulie
2510*98017a1fSRadu Bulie if ((sel & TCAM_SEL_ENTRY) && ix >= entry_count)
2511*98017a1fSRadu Bulie return CMD_RET_FAILURE;
2512*98017a1fSRadu Bulie
2513*98017a1fSRadu Bulie if (!(sel & TCAM_SEL_ENTRY))
2514*98017a1fSRadu Bulie value |= VSC9953_VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS;
2515*98017a1fSRadu Bulie
2516*98017a1fSRadu Bulie if (!(sel & TCAM_SEL_ACTION))
2517*98017a1fSRadu Bulie value |= VSC9953_VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS;
2518*98017a1fSRadu Bulie
2519*98017a1fSRadu Bulie if (!(sel & TCAM_SEL_COUNTER))
2520*98017a1fSRadu Bulie value |= VSC9953_VCAP_UPDATE_CTRL_UPDATE_CNT_DIS;
2521*98017a1fSRadu Bulie
2522*98017a1fSRadu Bulie out_le32((unsigned int *)(VSC9953_OFFSET +
2523*98017a1fSRadu Bulie VSC9953_VCAP_CFG_UPDATE_CTRL(tgt)), value);
2524*98017a1fSRadu Bulie
2525*98017a1fSRadu Bulie do {
2526*98017a1fSRadu Bulie value = in_le32((unsigned int *)(VSC9953_OFFSET +
2527*98017a1fSRadu Bulie VSC9953_VCAP_CFG_UPDATE_CTRL(tgt)));
2528*98017a1fSRadu Bulie
2529*98017a1fSRadu Bulie } while (value & VSC9953_VCAP_UPDATE_CTRL_UPDATE_SHOT);
2530*98017a1fSRadu Bulie
2531*98017a1fSRadu Bulie return CMD_RET_SUCCESS;
2532*98017a1fSRadu Bulie }
2533*98017a1fSRadu Bulie
vsc9953_vcap_init(void)2534*98017a1fSRadu Bulie static void vsc9953_vcap_init(void)
2535*98017a1fSRadu Bulie {
2536*98017a1fSRadu Bulie u32 tgt = VSC9953_ES0;
2537*98017a1fSRadu Bulie int cmd_ret;
2538*98017a1fSRadu Bulie
2539*98017a1fSRadu Bulie /* write entries */
2540*98017a1fSRadu Bulie vcap_entry2cache_init(tgt, ENTRY_WORDS_ES0);
2541*98017a1fSRadu Bulie cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE, TCAM_SEL_ENTRY,
2542*98017a1fSRadu Bulie ENTRY_WORDS_ES0);
2543*98017a1fSRadu Bulie if (cmd_ret != CMD_RET_SUCCESS)
2544*98017a1fSRadu Bulie debug("VSC9953:%d invalid TCAM_SEL_ENTRY\n",
2545*98017a1fSRadu Bulie __LINE__);
2546*98017a1fSRadu Bulie
2547*98017a1fSRadu Bulie /* write actions and counters */
2548*98017a1fSRadu Bulie vcap_action2cache_init(tgt, BITS_TO_DWORD(ES0_ACT_WIDTH),
2549*98017a1fSRadu Bulie BITS_TO_DWORD(ES0_CNT_WIDTH));
2550*98017a1fSRadu Bulie out_le32((unsigned int *)(VSC9953_OFFSET +
2551*98017a1fSRadu Bulie VSC9953_VCAP_CFG_MV_CFG(tgt)),
2552*98017a1fSRadu Bulie VSC9953_VCAP_CFG_MV_CFG_SIZE(ES0_ACT_COUNT));
2553*98017a1fSRadu Bulie cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE,
2554*98017a1fSRadu Bulie TCAM_SEL_ACTION | TCAM_SEL_COUNTER, ENTRY_WORDS_ES0);
2555*98017a1fSRadu Bulie if (cmd_ret != CMD_RET_SUCCESS)
2556*98017a1fSRadu Bulie debug("VSC9953:%d invalid TCAM_SEL_ACTION | TCAM_SEL_COUNTER\n",
2557*98017a1fSRadu Bulie __LINE__);
2558*98017a1fSRadu Bulie
2559*98017a1fSRadu Bulie tgt = VSC9953_IS1;
2560*98017a1fSRadu Bulie
2561*98017a1fSRadu Bulie /* write entries */
2562*98017a1fSRadu Bulie vcap_entry2cache_init(tgt, ENTRY_WORDS_IS1);
2563*98017a1fSRadu Bulie cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE, TCAM_SEL_ENTRY,
2564*98017a1fSRadu Bulie ENTRY_WORDS_IS1);
2565*98017a1fSRadu Bulie if (cmd_ret != CMD_RET_SUCCESS)
2566*98017a1fSRadu Bulie debug("VSC9953:%d invalid TCAM_SEL_ENTRY\n",
2567*98017a1fSRadu Bulie __LINE__);
2568*98017a1fSRadu Bulie
2569*98017a1fSRadu Bulie /* write actions and counters */
2570*98017a1fSRadu Bulie vcap_action2cache_init(tgt, BITS_TO_DWORD(IS1_ACT_WIDTH),
2571*98017a1fSRadu Bulie BITS_TO_DWORD(IS1_CNT_WIDTH));
2572*98017a1fSRadu Bulie out_le32((unsigned int *)(VSC9953_OFFSET +
2573*98017a1fSRadu Bulie VSC9953_VCAP_CFG_MV_CFG(tgt)),
2574*98017a1fSRadu Bulie VSC9953_VCAP_CFG_MV_CFG_SIZE(IS1_ACT_COUNT));
2575*98017a1fSRadu Bulie cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE,
2576*98017a1fSRadu Bulie TCAM_SEL_ACTION | TCAM_SEL_COUNTER, ENTRY_WORDS_IS1);
2577*98017a1fSRadu Bulie if (cmd_ret != CMD_RET_SUCCESS)
2578*98017a1fSRadu Bulie debug("VSC9953:%d invalid TCAM_SEL_ACTION | TCAM_SEL_COUNTER\n",
2579*98017a1fSRadu Bulie __LINE__);
2580*98017a1fSRadu Bulie
2581*98017a1fSRadu Bulie tgt = VSC9953_IS2;
2582*98017a1fSRadu Bulie
2583*98017a1fSRadu Bulie /* write entries */
2584*98017a1fSRadu Bulie vcap_entry2cache_init(tgt, ENTRY_WORDS_IS2);
2585*98017a1fSRadu Bulie cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE, TCAM_SEL_ENTRY,
2586*98017a1fSRadu Bulie ENTRY_WORDS_IS2);
2587*98017a1fSRadu Bulie if (cmd_ret != CMD_RET_SUCCESS)
2588*98017a1fSRadu Bulie debug("VSC9953:%d invalid selection: TCAM_SEL_ENTRY\n",
2589*98017a1fSRadu Bulie __LINE__);
2590*98017a1fSRadu Bulie
2591*98017a1fSRadu Bulie /* write actions and counters */
2592*98017a1fSRadu Bulie vcap_action2cache_init(tgt, BITS_TO_DWORD(IS2_ACT_WIDTH),
2593*98017a1fSRadu Bulie BITS_TO_DWORD(IS2_CNT_WIDTH));
2594*98017a1fSRadu Bulie out_le32((unsigned int *)(VSC9953_OFFSET +
2595*98017a1fSRadu Bulie VSC9953_VCAP_CFG_MV_CFG(tgt)),
2596*98017a1fSRadu Bulie VSC9953_VCAP_CFG_MV_CFG_SIZE(IS2_ACT_COUNT));
2597*98017a1fSRadu Bulie cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE,
2598*98017a1fSRadu Bulie TCAM_SEL_ACTION | TCAM_SEL_COUNTER, ENTRY_WORDS_IS2);
2599*98017a1fSRadu Bulie if (cmd_ret != CMD_RET_SUCCESS)
2600*98017a1fSRadu Bulie debug("VSC9953:%d invalid TCAM_SEL_ACTION | TCAM_SEL_COUNTER\n",
2601*98017a1fSRadu Bulie __LINE__);
2602*98017a1fSRadu Bulie }
2603*98017a1fSRadu Bulie
vsc9953_init(bd_t * bis)26046706b115SCodrin Ciubotariu void vsc9953_init(bd_t *bis)
26056706b115SCodrin Ciubotariu {
26063cc8cfffSCodrin Ciubotariu u32 i;
26073cc8cfffSCodrin Ciubotariu u32 hdx_cfg = 0;
26083cc8cfffSCodrin Ciubotariu u32 phy_addr = 0;
26096706b115SCodrin Ciubotariu int timeout;
26106706b115SCodrin Ciubotariu struct vsc9953_system_reg *l2sys_reg;
26116706b115SCodrin Ciubotariu struct vsc9953_qsys_reg *l2qsys_reg;
26126706b115SCodrin Ciubotariu struct vsc9953_dev_gmii *l2dev_gmii_reg;
26136706b115SCodrin Ciubotariu struct vsc9953_analyzer *l2ana_reg;
26146706b115SCodrin Ciubotariu struct vsc9953_devcpu_gcb *l2dev_gcb;
26156706b115SCodrin Ciubotariu
26166706b115SCodrin Ciubotariu l2dev_gmii_reg = (struct vsc9953_dev_gmii *)(VSC9953_OFFSET +
26176706b115SCodrin Ciubotariu VSC9953_DEV_GMII_OFFSET);
26186706b115SCodrin Ciubotariu
26196706b115SCodrin Ciubotariu l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
26206706b115SCodrin Ciubotariu VSC9953_ANA_OFFSET);
26216706b115SCodrin Ciubotariu
26226706b115SCodrin Ciubotariu l2sys_reg = (struct vsc9953_system_reg *)(VSC9953_OFFSET +
26236706b115SCodrin Ciubotariu VSC9953_SYS_OFFSET);
26246706b115SCodrin Ciubotariu
26256706b115SCodrin Ciubotariu l2qsys_reg = (struct vsc9953_qsys_reg *)(VSC9953_OFFSET +
26266706b115SCodrin Ciubotariu VSC9953_QSYS_OFFSET);
26276706b115SCodrin Ciubotariu
26286706b115SCodrin Ciubotariu l2dev_gcb = (struct vsc9953_devcpu_gcb *)(VSC9953_OFFSET +
26296706b115SCodrin Ciubotariu VSC9953_DEVCPU_GCB);
26306706b115SCodrin Ciubotariu
26316706b115SCodrin Ciubotariu out_le32(&l2dev_gcb->chip_regs.soft_rst,
2632c4390486SCodrin Ciubotariu VSC9953_SOFT_SWC_RST_ENA);
26336706b115SCodrin Ciubotariu timeout = 50000;
26346706b115SCodrin Ciubotariu while ((in_le32(&l2dev_gcb->chip_regs.soft_rst) &
2635c4390486SCodrin Ciubotariu VSC9953_SOFT_SWC_RST_ENA) && --timeout)
26366706b115SCodrin Ciubotariu udelay(1); /* busy wait for vsc9953 soft reset */
26376706b115SCodrin Ciubotariu if (timeout == 0)
26386706b115SCodrin Ciubotariu debug("Timeout waiting for VSC9953 to reset\n");
26396706b115SCodrin Ciubotariu
2640c4390486SCodrin Ciubotariu out_le32(&l2sys_reg->sys.reset_cfg, VSC9953_MEM_ENABLE |
2641c4390486SCodrin Ciubotariu VSC9953_MEM_INIT);
26426706b115SCodrin Ciubotariu
26436706b115SCodrin Ciubotariu timeout = 50000;
26446706b115SCodrin Ciubotariu while ((in_le32(&l2sys_reg->sys.reset_cfg) &
2645c4390486SCodrin Ciubotariu VSC9953_MEM_INIT) && --timeout)
26466706b115SCodrin Ciubotariu udelay(1); /* busy wait for vsc9953 memory init */
26476706b115SCodrin Ciubotariu if (timeout == 0)
26486706b115SCodrin Ciubotariu debug("Timeout waiting for VSC9953 memory to initialize\n");
26496706b115SCodrin Ciubotariu
26506706b115SCodrin Ciubotariu out_le32(&l2sys_reg->sys.reset_cfg, (in_le32(&l2sys_reg->sys.reset_cfg)
2651c4390486SCodrin Ciubotariu | VSC9953_CORE_ENABLE));
26526706b115SCodrin Ciubotariu
26536706b115SCodrin Ciubotariu /* VSC9953 Setting to be done once only */
26546706b115SCodrin Ciubotariu out_le32(&l2qsys_reg->sys.ext_cpu_cfg, 0x00000b00);
26556706b115SCodrin Ciubotariu
26566706b115SCodrin Ciubotariu for (i = 0; i < VSC9953_MAX_PORTS; i++) {
26576706b115SCodrin Ciubotariu if (vsc9953_port_init(i))
26586706b115SCodrin Ciubotariu printf("Failed to initialize l2switch port %d\n", i);
26596706b115SCodrin Ciubotariu
266002c00f26SCodrin Ciubotariu if (!vsc9953_l2sw.port[i].enabled)
266102c00f26SCodrin Ciubotariu continue;
266202c00f26SCodrin Ciubotariu
26636706b115SCodrin Ciubotariu /* Enable VSC9953 GMII Ports Port ID 0 - 7 */
26646706b115SCodrin Ciubotariu if (VSC9953_INTERNAL_PORT_CHECK(i)) {
26656706b115SCodrin Ciubotariu out_le32(&l2ana_reg->pfc[i].pfc_cfg,
2666c4390486SCodrin Ciubotariu VSC9953_PFC_FC_QSGMII);
26676706b115SCodrin Ciubotariu out_le32(&l2sys_reg->pause_cfg.mac_fc_cfg[i],
2668c4390486SCodrin Ciubotariu VSC9953_MAC_FC_CFG_QSGMII);
26696706b115SCodrin Ciubotariu } else {
26706706b115SCodrin Ciubotariu out_le32(&l2ana_reg->pfc[i].pfc_cfg,
2671c4390486SCodrin Ciubotariu VSC9953_PFC_FC);
26726706b115SCodrin Ciubotariu out_le32(&l2sys_reg->pause_cfg.mac_fc_cfg[i],
2673c4390486SCodrin Ciubotariu VSC9953_MAC_FC_CFG);
26746706b115SCodrin Ciubotariu }
267502c00f26SCodrin Ciubotariu
267602c00f26SCodrin Ciubotariu l2dev_gmii_reg = (struct vsc9953_dev_gmii *)
267702c00f26SCodrin Ciubotariu (VSC9953_OFFSET + VSC9953_DEV_GMII_OFFSET +
267802c00f26SCodrin Ciubotariu T1040_SWITCH_GMII_DEV_OFFSET * i);
267902c00f26SCodrin Ciubotariu
26806706b115SCodrin Ciubotariu out_le32(&l2dev_gmii_reg->port_mode.clock_cfg,
2681c4390486SCodrin Ciubotariu VSC9953_CLOCK_CFG);
26826706b115SCodrin Ciubotariu out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_ena_cfg,
2683c4390486SCodrin Ciubotariu VSC9953_MAC_ENA_CFG);
26846706b115SCodrin Ciubotariu out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_mode_cfg,
2685c4390486SCodrin Ciubotariu VSC9953_MAC_MODE_CFG);
26866706b115SCodrin Ciubotariu out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_ifg_cfg,
2687c4390486SCodrin Ciubotariu VSC9953_MAC_IFG_CFG);
26886706b115SCodrin Ciubotariu /* mac_hdx_cfg varies with port id*/
2689c4390486SCodrin Ciubotariu hdx_cfg = VSC9953_MAC_HDX_CFG | (i << 16);
26906706b115SCodrin Ciubotariu out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_hdx_cfg, hdx_cfg);
26916706b115SCodrin Ciubotariu out_le32(&l2sys_reg->sys.front_port_mode[i],
2692c4390486SCodrin Ciubotariu VSC9953_FRONT_PORT_MODE);
2693fe91095bSCodrin Ciubotariu setbits_le32(&l2qsys_reg->sys.switch_port_mode[i],
2694c4390486SCodrin Ciubotariu VSC9953_PORT_ENA);
26956706b115SCodrin Ciubotariu out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_maxlen_cfg,
2696c4390486SCodrin Ciubotariu VSC9953_MAC_MAX_LEN);
26976706b115SCodrin Ciubotariu out_le32(&l2sys_reg->pause_cfg.pause_cfg[i],
2698c4390486SCodrin Ciubotariu VSC9953_PAUSE_CFG);
26996706b115SCodrin Ciubotariu /* WAIT FOR 2 us*/
27006706b115SCodrin Ciubotariu udelay(2);
27016706b115SCodrin Ciubotariu
27026706b115SCodrin Ciubotariu /* Initialize Lynx PHY Wrappers */
27036706b115SCodrin Ciubotariu phy_addr = 0;
27046706b115SCodrin Ciubotariu if (vsc9953_l2sw.port[i].enet_if ==
27056706b115SCodrin Ciubotariu PHY_INTERFACE_MODE_QSGMII)
27066706b115SCodrin Ciubotariu phy_addr = (i + 0x4) & 0x1F;
27076706b115SCodrin Ciubotariu else if (vsc9953_l2sw.port[i].enet_if ==
27086706b115SCodrin Ciubotariu PHY_INTERFACE_MODE_SGMII)
27096706b115SCodrin Ciubotariu phy_addr = (i + 1) & 0x1F;
27106706b115SCodrin Ciubotariu
27116706b115SCodrin Ciubotariu if (phy_addr) {
27126706b115SCodrin Ciubotariu /* SGMII IF mode + AN enable */
27136706b115SCodrin Ciubotariu vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
27146706b115SCodrin Ciubotariu 0x14, PHY_SGMII_IF_MODE_AN |
27156706b115SCodrin Ciubotariu PHY_SGMII_IF_MODE_SGMII);
27166706b115SCodrin Ciubotariu /* Dev ability according to SGMII specification */
27176706b115SCodrin Ciubotariu vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
27186706b115SCodrin Ciubotariu 0x4, PHY_SGMII_DEV_ABILITY_SGMII);
27196706b115SCodrin Ciubotariu /* Adjust link timer for SGMII
27206706b115SCodrin Ciubotariu * 1.6 ms in units of 8 ns = 2 * 10^5 = 0x30d40
27216706b115SCodrin Ciubotariu */
27226706b115SCodrin Ciubotariu vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
27236706b115SCodrin Ciubotariu 0x13, 0x0003);
27246706b115SCodrin Ciubotariu vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
27256706b115SCodrin Ciubotariu 0x12, 0x0d40);
27266706b115SCodrin Ciubotariu /* Restart AN */
27276706b115SCodrin Ciubotariu vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
27286706b115SCodrin Ciubotariu 0x0, PHY_SGMII_CR_DEF_VAL |
27296706b115SCodrin Ciubotariu PHY_SGMII_CR_RESET_AN);
27306706b115SCodrin Ciubotariu
27316706b115SCodrin Ciubotariu timeout = 50000;
27326706b115SCodrin Ciubotariu while ((vsc9953_mdio_read(&l2dev_gcb->mii_mng[0],
27336706b115SCodrin Ciubotariu phy_addr, 0x01) & 0x0020) && --timeout)
27346706b115SCodrin Ciubotariu udelay(1); /* wait for AN to complete */
27356706b115SCodrin Ciubotariu if (timeout == 0)
27366706b115SCodrin Ciubotariu debug("Timeout waiting for AN to complete\n");
27376706b115SCodrin Ciubotariu }
27386706b115SCodrin Ciubotariu }
27396706b115SCodrin Ciubotariu
2740*98017a1fSRadu Bulie vsc9953_vcap_init();
27419de05987SCodrin Ciubotariu vsc9953_default_configuration();
27429de05987SCodrin Ciubotariu
274324a23debSCodrin Ciubotariu #ifdef CONFIG_CMD_ETHSW
274424a23debSCodrin Ciubotariu if (ethsw_define_functions(&vsc9953_cmd_func) < 0)
274524a23debSCodrin Ciubotariu debug("Unable to use \"ethsw\" commands\n");
274624a23debSCodrin Ciubotariu #endif
274724a23debSCodrin Ciubotariu
27486706b115SCodrin Ciubotariu printf("VSC9953 L2 switch initialized\n");
27496706b115SCodrin Ciubotariu return;
27506706b115SCodrin Ciubotariu }
2751