195711cd5SPawel Dembicki // SPDX-License-Identifier: GPL-2.0 295711cd5SPawel Dembicki /* DSA driver for: 395711cd5SPawel Dembicki * Vitesse VSC7385 SparX-G5 5+1-port Integrated Gigabit Ethernet Switch 495711cd5SPawel Dembicki * Vitesse VSC7388 SparX-G8 8-port Integrated Gigabit Ethernet Switch 595711cd5SPawel Dembicki * Vitesse VSC7395 SparX-G5e 5+1-port Integrated Gigabit Ethernet Switch 695711cd5SPawel Dembicki * Vitesse VSC7398 SparX-G8e 8-port Integrated Gigabit Ethernet Switch 795711cd5SPawel Dembicki * 895711cd5SPawel Dembicki * These switches have a built-in 8051 CPU and can download and execute a 995711cd5SPawel Dembicki * firmware in this CPU. They can also be configured to use an external CPU 1095711cd5SPawel Dembicki * handling the switch in a memory-mapped manner by connecting to that external 1195711cd5SPawel Dembicki * CPU's memory bus. 1295711cd5SPawel Dembicki * 1395711cd5SPawel Dembicki * Copyright (C) 2018 Linus Wallej <linus.walleij@linaro.org> 1495711cd5SPawel Dembicki * Includes portions of code from the firmware uploader by: 1595711cd5SPawel Dembicki * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> 1695711cd5SPawel Dembicki */ 1795711cd5SPawel Dembicki #include <linux/kernel.h> 1895711cd5SPawel Dembicki #include <linux/module.h> 1995711cd5SPawel Dembicki #include <linux/device.h> 20eb7e33d0SPawel Dembicki #include <linux/iopoll.h> 2195711cd5SPawel Dembicki #include <linux/of.h> 2295711cd5SPawel Dembicki #include <linux/of_mdio.h> 2395711cd5SPawel Dembicki #include <linux/bitops.h> 242524d6c2SPawel Dembicki #include <linux/bitfield.h> 2595711cd5SPawel Dembicki #include <linux/if_bridge.h> 266b783dedSPawel Dembicki #include <linux/if_vlan.h> 2795711cd5SPawel Dembicki #include <linux/etherdevice.h> 2895711cd5SPawel Dembicki #include <linux/gpio/consumer.h> 2995711cd5SPawel Dembicki #include <linux/gpio/driver.h> 306b783dedSPawel Dembicki #include <linux/dsa/8021q.h> 3195711cd5SPawel Dembicki #include <linux/random.h> 3295711cd5SPawel Dembicki #include <net/dsa.h> 3395711cd5SPawel Dembicki 3495711cd5SPawel Dembicki #include "vitesse-vsc73xx.h" 3595711cd5SPawel Dembicki 3695711cd5SPawel Dembicki #define VSC73XX_BLOCK_MAC 0x1 /* Subblocks 0-4, 6 (CPU port) */ 3795711cd5SPawel Dembicki #define VSC73XX_BLOCK_ANALYZER 0x2 /* Only subblock 0 */ 3895711cd5SPawel Dembicki #define VSC73XX_BLOCK_MII 0x3 /* Subblocks 0 and 1 */ 3995711cd5SPawel Dembicki #define VSC73XX_BLOCK_MEMINIT 0x3 /* Only subblock 2 */ 4095711cd5SPawel Dembicki #define VSC73XX_BLOCK_CAPTURE 0x4 /* Only subblock 2 */ 4195711cd5SPawel Dembicki #define VSC73XX_BLOCK_ARBITER 0x5 /* Only subblock 0 */ 4295711cd5SPawel Dembicki #define VSC73XX_BLOCK_SYSTEM 0x7 /* Only subblock 0 */ 4395711cd5SPawel Dembicki 448d5be2c4SPawel Dembicki /* MII Block subblock */ 458d5be2c4SPawel Dembicki #define VSC73XX_BLOCK_MII_INTERNAL 0x0 /* Internal MDIO subblock */ 462524d6c2SPawel Dembicki #define VSC73XX_BLOCK_MII_EXTERNAL 0x1 /* External MDIO subblock */ 478d5be2c4SPawel Dembicki 4895711cd5SPawel Dembicki #define CPU_PORT 6 /* CPU port */ 49*075e3d30SPawel Dembicki #define VSC73XX_NUM_FDB_ROWS 2048 50*075e3d30SPawel Dembicki #define VSC73XX_NUM_BUCKETS 4 5195711cd5SPawel Dembicki 5295711cd5SPawel Dembicki /* MAC Block registers */ 5395711cd5SPawel Dembicki #define VSC73XX_MAC_CFG 0x00 5495711cd5SPawel Dembicki #define VSC73XX_MACHDXGAP 0x02 5595711cd5SPawel Dembicki #define VSC73XX_FCCONF 0x04 5695711cd5SPawel Dembicki #define VSC73XX_FCMACHI 0x08 5795711cd5SPawel Dembicki #define VSC73XX_FCMACLO 0x0c 5895711cd5SPawel Dembicki #define VSC73XX_MAXLEN 0x10 5995711cd5SPawel Dembicki #define VSC73XX_ADVPORTM 0x19 6095711cd5SPawel Dembicki #define VSC73XX_TXUPDCFG 0x24 6195711cd5SPawel Dembicki #define VSC73XX_TXQ_SELECT_CFG 0x28 6295711cd5SPawel Dembicki #define VSC73XX_RXOCT 0x50 6395711cd5SPawel Dembicki #define VSC73XX_TXOCT 0x51 6495711cd5SPawel Dembicki #define VSC73XX_C_RX0 0x52 6595711cd5SPawel Dembicki #define VSC73XX_C_RX1 0x53 6695711cd5SPawel Dembicki #define VSC73XX_C_RX2 0x54 6795711cd5SPawel Dembicki #define VSC73XX_C_TX0 0x55 6895711cd5SPawel Dembicki #define VSC73XX_C_TX1 0x56 6995711cd5SPawel Dembicki #define VSC73XX_C_TX2 0x57 7095711cd5SPawel Dembicki #define VSC73XX_C_CFG 0x58 7195711cd5SPawel Dembicki #define VSC73XX_CAT_DROP 0x6e 7295711cd5SPawel Dembicki #define VSC73XX_CAT_PR_MISC_L2 0x6f 7395711cd5SPawel Dembicki #define VSC73XX_CAT_PR_USR_PRIO 0x75 746b783dedSPawel Dembicki #define VSC73XX_CAT_VLAN_MISC 0x79 756b783dedSPawel Dembicki #define VSC73XX_CAT_PORT_VLAN 0x7a 7695711cd5SPawel Dembicki #define VSC73XX_Q_MISC_CONF 0xdf 7795711cd5SPawel Dembicki 7895711cd5SPawel Dembicki /* MAC_CFG register bits */ 7995711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_WEXC_DIS BIT(31) 8095711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_PORT_RST BIT(29) 8195711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_TX_EN BIT(28) 8295711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_SEED_LOAD BIT(27) 8395711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_SEED_MASK GENMASK(26, 19) 8495711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_SEED_OFFSET 19 8595711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_FDX BIT(18) 8695711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_GIGA_MODE BIT(17) 8795711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_RX_EN BIT(16) 8895711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_VLAN_DBLAWR BIT(15) 8995711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_VLAN_AWR BIT(14) 9095711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_100_BASE_T BIT(13) /* Not in manual */ 9195711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_TX_IPG_MASK GENMASK(10, 6) 9295711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_TX_IPG_OFFSET 6 9395711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_TX_IPG_1000M (6 << VSC73XX_MAC_CFG_TX_IPG_OFFSET) 9495711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_TX_IPG_100_10M (17 << VSC73XX_MAC_CFG_TX_IPG_OFFSET) 9595711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_MAC_RX_RST BIT(5) 9695711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_MAC_TX_RST BIT(4) 9795711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_CLK_SEL_MASK GENMASK(2, 0) 9895711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_CLK_SEL_OFFSET 0 9995711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_CLK_SEL_1000M 1 10095711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_CLK_SEL_100M 2 10195711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_CLK_SEL_10M 3 10295711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_CLK_SEL_EXT 4 10395711cd5SPawel Dembicki 10495711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_1000M_F_PHY (VSC73XX_MAC_CFG_FDX | \ 10595711cd5SPawel Dembicki VSC73XX_MAC_CFG_GIGA_MODE | \ 10695711cd5SPawel Dembicki VSC73XX_MAC_CFG_TX_IPG_1000M | \ 10795711cd5SPawel Dembicki VSC73XX_MAC_CFG_CLK_SEL_EXT) 10895711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_100_10M_F_PHY (VSC73XX_MAC_CFG_FDX | \ 10995711cd5SPawel Dembicki VSC73XX_MAC_CFG_TX_IPG_100_10M | \ 11095711cd5SPawel Dembicki VSC73XX_MAC_CFG_CLK_SEL_EXT) 11195711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_100_10M_H_PHY (VSC73XX_MAC_CFG_TX_IPG_100_10M | \ 11295711cd5SPawel Dembicki VSC73XX_MAC_CFG_CLK_SEL_EXT) 11395711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_1000M_F_RGMII (VSC73XX_MAC_CFG_FDX | \ 11495711cd5SPawel Dembicki VSC73XX_MAC_CFG_GIGA_MODE | \ 11595711cd5SPawel Dembicki VSC73XX_MAC_CFG_TX_IPG_1000M | \ 11695711cd5SPawel Dembicki VSC73XX_MAC_CFG_CLK_SEL_1000M) 11795711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_RESET (VSC73XX_MAC_CFG_PORT_RST | \ 11895711cd5SPawel Dembicki VSC73XX_MAC_CFG_MAC_RX_RST | \ 11995711cd5SPawel Dembicki VSC73XX_MAC_CFG_MAC_TX_RST) 12095711cd5SPawel Dembicki 12195711cd5SPawel Dembicki /* Flow control register bits */ 12295711cd5SPawel Dembicki #define VSC73XX_FCCONF_ZERO_PAUSE_EN BIT(17) 12395711cd5SPawel Dembicki #define VSC73XX_FCCONF_FLOW_CTRL_OBEY BIT(16) 12495711cd5SPawel Dembicki #define VSC73XX_FCCONF_PAUSE_VAL_MASK GENMASK(15, 0) 12595711cd5SPawel Dembicki 12695711cd5SPawel Dembicki /* ADVPORTM advanced port setup register bits */ 12795711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_IFG_PPM BIT(7) 12895711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_EXC_COL_CONT BIT(6) 12995711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_EXT_PORT BIT(5) 13095711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_INV_GTX BIT(4) 13195711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_ENA_GTX BIT(3) 13295711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_DDR_MODE BIT(2) 13395711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_IO_LOOPBACK BIT(1) 13495711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_HOST_LOOPBACK BIT(0) 13595711cd5SPawel Dembicki 1366b783dedSPawel Dembicki /* TXUPDCFG transmit modify setup bits */ 1376b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_DSCP_REWR_MODE GENMASK(20, 19) 1386b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_DSCP_REWR_ENA BIT(18) 1396b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_TX_INT_TO_USRPRIO_ENA BIT(17) 1406b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_TX_UNTAGGED_VID GENMASK(15, 4) 1416b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_TX_UNTAGGED_VID_ENA BIT(3) 1426b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_TX_UPDATE_CRC_CPU_ENA BIT(1) 1436b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_TX_INSERT_TAG BIT(0) 1446b783dedSPawel Dembicki 1456b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_TX_UNTAGGED_VID_SHIFT 4 1466b783dedSPawel Dembicki 14795711cd5SPawel Dembicki /* CAT_DROP categorizer frame dropping register bits */ 14895711cd5SPawel Dembicki #define VSC73XX_CAT_DROP_DROP_MC_SMAC_ENA BIT(6) 14995711cd5SPawel Dembicki #define VSC73XX_CAT_DROP_FWD_CTRL_ENA BIT(4) 15095711cd5SPawel Dembicki #define VSC73XX_CAT_DROP_FWD_PAUSE_ENA BIT(3) 15195711cd5SPawel Dembicki #define VSC73XX_CAT_DROP_UNTAGGED_ENA BIT(2) 15295711cd5SPawel Dembicki #define VSC73XX_CAT_DROP_TAGGED_ENA BIT(1) 15395711cd5SPawel Dembicki #define VSC73XX_CAT_DROP_NULL_MAC_ENA BIT(0) 15495711cd5SPawel Dembicki 15595711cd5SPawel Dembicki #define VSC73XX_Q_MISC_CONF_EXTENT_MEM BIT(31) 15695711cd5SPawel Dembicki #define VSC73XX_Q_MISC_CONF_EARLY_TX_MASK GENMASK(4, 1) 15795711cd5SPawel Dembicki #define VSC73XX_Q_MISC_CONF_EARLY_TX_512 (1 << 1) 15895711cd5SPawel Dembicki #define VSC73XX_Q_MISC_CONF_MAC_PAUSE_MODE BIT(0) 15995711cd5SPawel Dembicki 1606b783dedSPawel Dembicki /* CAT_VLAN_MISC categorizer VLAN miscellaneous bits */ 1616b783dedSPawel Dembicki #define VSC73XX_CAT_VLAN_MISC_VLAN_TCI_IGNORE_ENA BIT(8) 1626b783dedSPawel Dembicki #define VSC73XX_CAT_VLAN_MISC_VLAN_KEEP_TAG_ENA BIT(7) 1636b783dedSPawel Dembicki 1646b783dedSPawel Dembicki /* CAT_PORT_VLAN categorizer port VLAN */ 1656b783dedSPawel Dembicki #define VSC73XX_CAT_PORT_VLAN_VLAN_CFI BIT(15) 1666b783dedSPawel Dembicki #define VSC73XX_CAT_PORT_VLAN_VLAN_USR_PRIO GENMASK(14, 12) 1676b783dedSPawel Dembicki #define VSC73XX_CAT_PORT_VLAN_VLAN_VID GENMASK(11, 0) 1686b783dedSPawel Dembicki 16995711cd5SPawel Dembicki /* Frame analyzer block 2 registers */ 17095711cd5SPawel Dembicki #define VSC73XX_STORMLIMIT 0x02 17195711cd5SPawel Dembicki #define VSC73XX_ADVLEARN 0x03 17295711cd5SPawel Dembicki #define VSC73XX_IFLODMSK 0x04 17395711cd5SPawel Dembicki #define VSC73XX_VLANMASK 0x05 17495711cd5SPawel Dembicki #define VSC73XX_MACHDATA 0x06 17595711cd5SPawel Dembicki #define VSC73XX_MACLDATA 0x07 17695711cd5SPawel Dembicki #define VSC73XX_ANMOVED 0x08 17795711cd5SPawel Dembicki #define VSC73XX_ANAGEFIL 0x09 17895711cd5SPawel Dembicki #define VSC73XX_ANEVENTS 0x0a 17995711cd5SPawel Dembicki #define VSC73XX_ANCNTMASK 0x0b 18095711cd5SPawel Dembicki #define VSC73XX_ANCNTVAL 0x0c 18195711cd5SPawel Dembicki #define VSC73XX_LEARNMASK 0x0d 18295711cd5SPawel Dembicki #define VSC73XX_UFLODMASK 0x0e 18395711cd5SPawel Dembicki #define VSC73XX_MFLODMASK 0x0f 18495711cd5SPawel Dembicki #define VSC73XX_RECVMASK 0x10 18595711cd5SPawel Dembicki #define VSC73XX_AGGRCTRL 0x20 18695711cd5SPawel Dembicki #define VSC73XX_AGGRMSKS 0x30 /* Until 0x3f */ 18795711cd5SPawel Dembicki #define VSC73XX_DSTMASKS 0x40 /* Until 0x7f */ 18895711cd5SPawel Dembicki #define VSC73XX_SRCMASKS 0x80 /* Until 0x87 */ 18995711cd5SPawel Dembicki #define VSC73XX_CAPENAB 0xa0 19095711cd5SPawel Dembicki #define VSC73XX_MACACCESS 0xb0 19195711cd5SPawel Dembicki #define VSC73XX_IPMCACCESS 0xb1 19295711cd5SPawel Dembicki #define VSC73XX_MACTINDX 0xc0 19395711cd5SPawel Dembicki #define VSC73XX_VLANACCESS 0xd0 19495711cd5SPawel Dembicki #define VSC73XX_VLANTIDX 0xe0 19595711cd5SPawel Dembicki #define VSC73XX_AGENCTRL 0xf0 19695711cd5SPawel Dembicki #define VSC73XX_CAPRST 0xff 19795711cd5SPawel Dembicki 1981e5b23e5SPawel Dembicki #define VSC73XX_SRCMASKS_CPU_COPY BIT(27) 1991e5b23e5SPawel Dembicki #define VSC73XX_SRCMASKS_MIRROR BIT(26) 2001e5b23e5SPawel Dembicki #define VSC73XX_SRCMASKS_PORTS_MASK GENMASK(7, 0) 2011e5b23e5SPawel Dembicki 202*075e3d30SPawel Dembicki #define VSC73XX_MACHDATA_VID GENMASK(27, 16) 203*075e3d30SPawel Dembicki #define VSC73XX_MACHDATA_MAC0 GENMASK(15, 8) 204*075e3d30SPawel Dembicki #define VSC73XX_MACHDATA_MAC1 GENMASK(7, 0) 205*075e3d30SPawel Dembicki #define VSC73XX_MACLDATA_MAC2 GENMASK(31, 24) 206*075e3d30SPawel Dembicki #define VSC73XX_MACLDATA_MAC3 GENMASK(23, 16) 207*075e3d30SPawel Dembicki #define VSC73XX_MACLDATA_MAC4 GENMASK(15, 8) 208*075e3d30SPawel Dembicki #define VSC73XX_MACLDATA_MAC5 GENMASK(7, 0) 209*075e3d30SPawel Dembicki 210*075e3d30SPawel Dembicki #define VSC73XX_HASH0_VID_FROM_MASK GENMASK(5, 0) 211*075e3d30SPawel Dembicki #define VSC73XX_HASH0_MAC0_FROM_MASK GENMASK(7, 4) 212*075e3d30SPawel Dembicki #define VSC73XX_HASH1_MAC0_FROM_MASK GENMASK(3, 0) 213*075e3d30SPawel Dembicki #define VSC73XX_HASH1_MAC1_FROM_MASK GENMASK(7, 1) 214*075e3d30SPawel Dembicki #define VSC73XX_HASH2_MAC1_FROM_MASK BIT(0) 215*075e3d30SPawel Dembicki #define VSC73XX_HASH2_MAC2_FROM_MASK GENMASK(7, 0) 216*075e3d30SPawel Dembicki #define VSC73XX_HASH2_MAC3_FROM_MASK GENMASK(7, 6) 217*075e3d30SPawel Dembicki #define VSC73XX_HASH3_MAC3_FROM_MASK GENMASK(5, 0) 218*075e3d30SPawel Dembicki #define VSC73XX_HASH3_MAC4_FROM_MASK GENMASK(7, 3) 219*075e3d30SPawel Dembicki #define VSC73XX_HASH4_MAC4_FROM_MASK GENMASK(2, 0) 220*075e3d30SPawel Dembicki 221*075e3d30SPawel Dembicki #define VSC73XX_HASH0_VID_TO_MASK GENMASK(9, 4) 222*075e3d30SPawel Dembicki #define VSC73XX_HASH0_MAC0_TO_MASK GENMASK(3, 0) 223*075e3d30SPawel Dembicki #define VSC73XX_HASH1_MAC0_TO_MASK GENMASK(10, 7) 224*075e3d30SPawel Dembicki #define VSC73XX_HASH1_MAC1_TO_MASK GENMASK(6, 0) 225*075e3d30SPawel Dembicki #define VSC73XX_HASH2_MAC1_TO_MASK BIT(10) 226*075e3d30SPawel Dembicki #define VSC73XX_HASH2_MAC2_TO_MASK GENMASK(9, 2) 227*075e3d30SPawel Dembicki #define VSC73XX_HASH2_MAC3_TO_MASK GENMASK(1, 0) 228*075e3d30SPawel Dembicki #define VSC73XX_HASH3_MAC3_TO_MASK GENMASK(10, 5) 229*075e3d30SPawel Dembicki #define VSC73XX_HASH3_MAC4_TO_MASK GENMASK(4, 0) 230*075e3d30SPawel Dembicki #define VSC73XX_HASH4_MAC4_TO_MASK GENMASK(10, 8) 231*075e3d30SPawel Dembicki 232*075e3d30SPawel Dembicki #define VSC73XX_MACTINDX_SHADOW BIT(13) 233*075e3d30SPawel Dembicki #define VSC73XX_MACTINDX_BUCKET_MSK GENMASK(12, 11) 234*075e3d30SPawel Dembicki #define VSC73XX_MACTINDX_INDEX_MSK GENMASK(10, 0) 235*075e3d30SPawel Dembicki 23695711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CPU_COPY BIT(14) 23795711cd5SPawel Dembicki #define VSC73XX_MACACCESS_FWD_KILL BIT(13) 23895711cd5SPawel Dembicki #define VSC73XX_MACACCESS_IGNORE_VLAN BIT(12) 23995711cd5SPawel Dembicki #define VSC73XX_MACACCESS_AGED_FLAG BIT(11) 24095711cd5SPawel Dembicki #define VSC73XX_MACACCESS_VALID BIT(10) 24195711cd5SPawel Dembicki #define VSC73XX_MACACCESS_LOCKED BIT(9) 24295711cd5SPawel Dembicki #define VSC73XX_MACACCESS_DEST_IDX_MASK GENMASK(8, 3) 24395711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_MASK GENMASK(2, 0) 24495711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_IDLE 0 24595711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_LEARN 1 24695711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_FORGET 2 24795711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_AGE_TABLE 3 24895711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_FLUSH_TABLE 4 24995711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_CLEAR_TABLE 5 25095711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_READ_ENTRY 6 25195711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_WRITE_ENTRY 7 25295711cd5SPawel Dembicki 25395711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_LEARN_DISABLED BIT(30) 25495711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_MIRROR BIT(29) 25595711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_SRC_CHECK BIT(28) 25695711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_PORT_MASK GENMASK(9, 2) 2576b783dedSPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_PORT_MASK_SHIFT 2 2586b783dedSPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_MASK GENMASK(1, 0) 25995711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_IDLE 0 26095711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_READ_ENTRY 1 26195711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_WRITE_ENTRY 2 26295711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_CLEAR_TABLE 3 26395711cd5SPawel Dembicki 26495711cd5SPawel Dembicki /* MII block 3 registers */ 26595711cd5SPawel Dembicki #define VSC73XX_MII_STAT 0x0 26695711cd5SPawel Dembicki #define VSC73XX_MII_CMD 0x1 26795711cd5SPawel Dembicki #define VSC73XX_MII_DATA 0x2 2688d5be2c4SPawel Dembicki #define VSC73XX_MII_MPRES 0x3 2698d5be2c4SPawel Dembicki 2702524d6c2SPawel Dembicki #define VSC73XX_MII_STAT_BUSY BIT(3) 2712524d6c2SPawel Dembicki #define VSC73XX_MII_STAT_READ BIT(2) 2722524d6c2SPawel Dembicki #define VSC73XX_MII_STAT_WRITE BIT(1) 2732524d6c2SPawel Dembicki 2742524d6c2SPawel Dembicki #define VSC73XX_MII_CMD_SCAN BIT(27) 2752524d6c2SPawel Dembicki #define VSC73XX_MII_CMD_OPERATION BIT(26) 2762524d6c2SPawel Dembicki #define VSC73XX_MII_CMD_PHY_ADDR GENMASK(25, 21) 2772524d6c2SPawel Dembicki #define VSC73XX_MII_CMD_PHY_REG GENMASK(20, 16) 2782524d6c2SPawel Dembicki #define VSC73XX_MII_CMD_WRITE_DATA GENMASK(15, 0) 2792524d6c2SPawel Dembicki 2802524d6c2SPawel Dembicki #define VSC73XX_MII_DATA_FAILURE BIT(16) 2812524d6c2SPawel Dembicki #define VSC73XX_MII_DATA_READ_DATA GENMASK(15, 0) 2822524d6c2SPawel Dembicki 2838d5be2c4SPawel Dembicki #define VSC73XX_MII_MPRES_NOPREAMBLE BIT(6) 2848d5be2c4SPawel Dembicki #define VSC73XX_MII_MPRES_PRESCALEVAL GENMASK(5, 0) 2858d5be2c4SPawel Dembicki #define VSC73XX_MII_PRESCALEVAL_MIN 3 /* min allowed mdio clock prescaler */ 28695711cd5SPawel Dembicki 287fa63c643SPawel Dembicki #define VSC73XX_MII_STAT_BUSY BIT(3) 288fa63c643SPawel Dembicki 28995711cd5SPawel Dembicki /* Arbiter block 5 registers */ 29095711cd5SPawel Dembicki #define VSC73XX_ARBEMPTY 0x0c 29195711cd5SPawel Dembicki #define VSC73XX_ARBDISC 0x0e 29295711cd5SPawel Dembicki #define VSC73XX_SBACKWDROP 0x12 29395711cd5SPawel Dembicki #define VSC73XX_DBACKWDROP 0x13 29495711cd5SPawel Dembicki #define VSC73XX_ARBBURSTPROB 0x15 29595711cd5SPawel Dembicki 29695711cd5SPawel Dembicki /* System block 7 registers */ 29795711cd5SPawel Dembicki #define VSC73XX_ICPU_SIPAD 0x01 29895711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY 0x05 29995711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL 0x10 30095711cd5SPawel Dembicki #define VSC73XX_ICPU_ADDR 0x11 30195711cd5SPawel Dembicki #define VSC73XX_ICPU_SRAM 0x12 30295711cd5SPawel Dembicki #define VSC73XX_HWSEM 0x13 30395711cd5SPawel Dembicki #define VSC73XX_GLORESET 0x14 30495711cd5SPawel Dembicki #define VSC73XX_ICPU_MBOX_VAL 0x15 30595711cd5SPawel Dembicki #define VSC73XX_ICPU_MBOX_SET 0x16 30695711cd5SPawel Dembicki #define VSC73XX_ICPU_MBOX_CLR 0x17 30795711cd5SPawel Dembicki #define VSC73XX_CHIPID 0x18 30895711cd5SPawel Dembicki #define VSC73XX_GPIO 0x34 30995711cd5SPawel Dembicki 31095711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_GTXDELAY_NONE 0 31195711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_GTXDELAY_1_4_NS 1 31295711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_GTXDELAY_1_7_NS 2 31395711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_GTXDELAY_2_0_NS 3 31495711cd5SPawel Dembicki 31595711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_RXDELAY_NONE (0 << 4) 31695711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_RXDELAY_1_4_NS (1 << 4) 31795711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_RXDELAY_1_7_NS (2 << 4) 31895711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_RXDELAY_2_0_NS (3 << 4) 31995711cd5SPawel Dembicki 32095711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_WATCHDOG_RST BIT(31) 32195711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_CLK_DIV_MASK GENMASK(12, 8) 32295711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_SRST_HOLD BIT(7) 32395711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_ICPU_PI_EN BIT(6) 32495711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_BOOT_EN BIT(3) 32595711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_EXT_ACC_EN BIT(2) 32695711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_CLK_EN BIT(1) 32795711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_SRST BIT(0) 32895711cd5SPawel Dembicki 32995711cd5SPawel Dembicki #define VSC73XX_CHIPID_ID_SHIFT 12 33095711cd5SPawel Dembicki #define VSC73XX_CHIPID_ID_MASK 0xffff 33195711cd5SPawel Dembicki #define VSC73XX_CHIPID_REV_SHIFT 28 33295711cd5SPawel Dembicki #define VSC73XX_CHIPID_REV_MASK 0xf 33395711cd5SPawel Dembicki #define VSC73XX_CHIPID_ID_7385 0x7385 33495711cd5SPawel Dembicki #define VSC73XX_CHIPID_ID_7388 0x7388 33595711cd5SPawel Dembicki #define VSC73XX_CHIPID_ID_7395 0x7395 33695711cd5SPawel Dembicki #define VSC73XX_CHIPID_ID_7398 0x7398 33795711cd5SPawel Dembicki 33895711cd5SPawel Dembicki #define VSC73XX_GLORESET_STROBE BIT(4) 33995711cd5SPawel Dembicki #define VSC73XX_GLORESET_ICPU_LOCK BIT(3) 34095711cd5SPawel Dembicki #define VSC73XX_GLORESET_MEM_LOCK BIT(2) 34195711cd5SPawel Dembicki #define VSC73XX_GLORESET_PHY_RESET BIT(1) 34295711cd5SPawel Dembicki #define VSC73XX_GLORESET_MASTER_RESET BIT(0) 34395711cd5SPawel Dembicki 34495711cd5SPawel Dembicki #define VSC7385_CLOCK_DELAY ((3 << 4) | 3) 34595711cd5SPawel Dembicki #define VSC7385_CLOCK_DELAY_MASK ((3 << 4) | 3) 34695711cd5SPawel Dembicki 34795711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_STOP (VSC73XX_ICPU_CTRL_SRST_HOLD | \ 34895711cd5SPawel Dembicki VSC73XX_ICPU_CTRL_BOOT_EN | \ 34995711cd5SPawel Dembicki VSC73XX_ICPU_CTRL_EXT_ACC_EN) 35095711cd5SPawel Dembicki 35195711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_START (VSC73XX_ICPU_CTRL_CLK_DIV | \ 35295711cd5SPawel Dembicki VSC73XX_ICPU_CTRL_BOOT_EN | \ 35395711cd5SPawel Dembicki VSC73XX_ICPU_CTRL_CLK_EN | \ 35495711cd5SPawel Dembicki VSC73XX_ICPU_CTRL_SRST) 35595711cd5SPawel Dembicki 35695711cd5SPawel Dembicki #define IS_7385(a) ((a)->chipid == VSC73XX_CHIPID_ID_7385) 35795711cd5SPawel Dembicki #define IS_7388(a) ((a)->chipid == VSC73XX_CHIPID_ID_7388) 35895711cd5SPawel Dembicki #define IS_7395(a) ((a)->chipid == VSC73XX_CHIPID_ID_7395) 35995711cd5SPawel Dembicki #define IS_7398(a) ((a)->chipid == VSC73XX_CHIPID_ID_7398) 36095711cd5SPawel Dembicki #define IS_739X(a) (IS_7395(a) || IS_7398(a)) 36195711cd5SPawel Dembicki 362eb7e33d0SPawel Dembicki #define VSC73XX_POLL_SLEEP_US 1000 363fa63c643SPawel Dembicki #define VSC73XX_MDIO_POLL_SLEEP_US 5 364eb7e33d0SPawel Dembicki #define VSC73XX_POLL_TIMEOUT_US 10000 365eb7e33d0SPawel Dembicki 36695711cd5SPawel Dembicki struct vsc73xx_counter { 36795711cd5SPawel Dembicki u8 counter; 36895711cd5SPawel Dembicki const char *name; 36995711cd5SPawel Dembicki }; 37095711cd5SPawel Dembicki 371*075e3d30SPawel Dembicki struct vsc73xx_fdb { 372*075e3d30SPawel Dembicki u16 vid; 373*075e3d30SPawel Dembicki u8 port; 374*075e3d30SPawel Dembicki u8 mac[ETH_ALEN]; 375*075e3d30SPawel Dembicki bool valid; 376*075e3d30SPawel Dembicki }; 377*075e3d30SPawel Dembicki 37895711cd5SPawel Dembicki /* Counters are named according to the MIB standards where applicable. 37995711cd5SPawel Dembicki * Some counters are custom, non-standard. The standard counters are 38095711cd5SPawel Dembicki * named in accordance with RFC2819, RFC2021 and IEEE Std 802.3-2002 Annex 38195711cd5SPawel Dembicki * 30A Counters. 38295711cd5SPawel Dembicki */ 38395711cd5SPawel Dembicki static const struct vsc73xx_counter vsc73xx_rx_counters[] = { 38495711cd5SPawel Dembicki { 0, "RxEtherStatsPkts" }, 38595711cd5SPawel Dembicki { 1, "RxBroadcast+MulticastPkts" }, /* non-standard counter */ 38695711cd5SPawel Dembicki { 2, "RxTotalErrorPackets" }, /* non-standard counter */ 38795711cd5SPawel Dembicki { 3, "RxEtherStatsBroadcastPkts" }, 38895711cd5SPawel Dembicki { 4, "RxEtherStatsMulticastPkts" }, 38995711cd5SPawel Dembicki { 5, "RxEtherStatsPkts64Octets" }, 39095711cd5SPawel Dembicki { 6, "RxEtherStatsPkts65to127Octets" }, 39195711cd5SPawel Dembicki { 7, "RxEtherStatsPkts128to255Octets" }, 39295711cd5SPawel Dembicki { 8, "RxEtherStatsPkts256to511Octets" }, 39395711cd5SPawel Dembicki { 9, "RxEtherStatsPkts512to1023Octets" }, 39495711cd5SPawel Dembicki { 10, "RxEtherStatsPkts1024to1518Octets" }, 39595711cd5SPawel Dembicki { 11, "RxJumboFrames" }, /* non-standard counter */ 39695711cd5SPawel Dembicki { 12, "RxaPauseMACControlFramesTransmitted" }, 39795711cd5SPawel Dembicki { 13, "RxFIFODrops" }, /* non-standard counter */ 39895711cd5SPawel Dembicki { 14, "RxBackwardDrops" }, /* non-standard counter */ 39995711cd5SPawel Dembicki { 15, "RxClassifierDrops" }, /* non-standard counter */ 40095711cd5SPawel Dembicki { 16, "RxEtherStatsCRCAlignErrors" }, 40195711cd5SPawel Dembicki { 17, "RxEtherStatsUndersizePkts" }, 40295711cd5SPawel Dembicki { 18, "RxEtherStatsOversizePkts" }, 40395711cd5SPawel Dembicki { 19, "RxEtherStatsFragments" }, 40495711cd5SPawel Dembicki { 20, "RxEtherStatsJabbers" }, 40595711cd5SPawel Dembicki { 21, "RxaMACControlFramesReceived" }, 40695711cd5SPawel Dembicki /* 22-24 are undefined */ 40795711cd5SPawel Dembicki { 25, "RxaFramesReceivedOK" }, 40895711cd5SPawel Dembicki { 26, "RxQoSClass0" }, /* non-standard counter */ 40995711cd5SPawel Dembicki { 27, "RxQoSClass1" }, /* non-standard counter */ 41095711cd5SPawel Dembicki { 28, "RxQoSClass2" }, /* non-standard counter */ 41195711cd5SPawel Dembicki { 29, "RxQoSClass3" }, /* non-standard counter */ 41295711cd5SPawel Dembicki }; 41395711cd5SPawel Dembicki 41495711cd5SPawel Dembicki static const struct vsc73xx_counter vsc73xx_tx_counters[] = { 41595711cd5SPawel Dembicki { 0, "TxEtherStatsPkts" }, 41695711cd5SPawel Dembicki { 1, "TxBroadcast+MulticastPkts" }, /* non-standard counter */ 41795711cd5SPawel Dembicki { 2, "TxTotalErrorPackets" }, /* non-standard counter */ 41895711cd5SPawel Dembicki { 3, "TxEtherStatsBroadcastPkts" }, 41995711cd5SPawel Dembicki { 4, "TxEtherStatsMulticastPkts" }, 42095711cd5SPawel Dembicki { 5, "TxEtherStatsPkts64Octets" }, 42195711cd5SPawel Dembicki { 6, "TxEtherStatsPkts65to127Octets" }, 42295711cd5SPawel Dembicki { 7, "TxEtherStatsPkts128to255Octets" }, 42395711cd5SPawel Dembicki { 8, "TxEtherStatsPkts256to511Octets" }, 42495711cd5SPawel Dembicki { 9, "TxEtherStatsPkts512to1023Octets" }, 42595711cd5SPawel Dembicki { 10, "TxEtherStatsPkts1024to1518Octets" }, 42695711cd5SPawel Dembicki { 11, "TxJumboFrames" }, /* non-standard counter */ 42795711cd5SPawel Dembicki { 12, "TxaPauseMACControlFramesTransmitted" }, 42895711cd5SPawel Dembicki { 13, "TxFIFODrops" }, /* non-standard counter */ 42995711cd5SPawel Dembicki { 14, "TxDrops" }, /* non-standard counter */ 43095711cd5SPawel Dembicki { 15, "TxEtherStatsCollisions" }, 43195711cd5SPawel Dembicki { 16, "TxEtherStatsCRCAlignErrors" }, 43295711cd5SPawel Dembicki { 17, "TxEtherStatsUndersizePkts" }, 43395711cd5SPawel Dembicki { 18, "TxEtherStatsOversizePkts" }, 43495711cd5SPawel Dembicki { 19, "TxEtherStatsFragments" }, 43595711cd5SPawel Dembicki { 20, "TxEtherStatsJabbers" }, 43695711cd5SPawel Dembicki /* 21-24 are undefined */ 43795711cd5SPawel Dembicki { 25, "TxaFramesReceivedOK" }, 43895711cd5SPawel Dembicki { 26, "TxQoSClass0" }, /* non-standard counter */ 43995711cd5SPawel Dembicki { 27, "TxQoSClass1" }, /* non-standard counter */ 44095711cd5SPawel Dembicki { 28, "TxQoSClass2" }, /* non-standard counter */ 44195711cd5SPawel Dembicki { 29, "TxQoSClass3" }, /* non-standard counter */ 44295711cd5SPawel Dembicki }; 44395711cd5SPawel Dembicki 4446b783dedSPawel Dembicki struct vsc73xx_vlan_summary { 4456b783dedSPawel Dembicki size_t num_tagged; 4466b783dedSPawel Dembicki size_t num_untagged; 4476b783dedSPawel Dembicki }; 4486b783dedSPawel Dembicki 4496b783dedSPawel Dembicki enum vsc73xx_port_vlan_conf { 4506b783dedSPawel Dembicki VSC73XX_VLAN_FILTER, 4516b783dedSPawel Dembicki VSC73XX_VLAN_FILTER_UNTAG_ALL, 4526b783dedSPawel Dembicki VSC73XX_VLAN_IGNORE, 4536b783dedSPawel Dembicki }; 4546b783dedSPawel Dembicki 45595711cd5SPawel Dembicki int vsc73xx_is_addr_valid(u8 block, u8 subblock) 45695711cd5SPawel Dembicki { 45795711cd5SPawel Dembicki switch (block) { 45895711cd5SPawel Dembicki case VSC73XX_BLOCK_MAC: 45995711cd5SPawel Dembicki switch (subblock) { 46095711cd5SPawel Dembicki case 0 ... 4: 46195711cd5SPawel Dembicki case 6: 46295711cd5SPawel Dembicki return 1; 46395711cd5SPawel Dembicki } 46495711cd5SPawel Dembicki break; 46595711cd5SPawel Dembicki 46695711cd5SPawel Dembicki case VSC73XX_BLOCK_ANALYZER: 46795711cd5SPawel Dembicki case VSC73XX_BLOCK_SYSTEM: 46895711cd5SPawel Dembicki switch (subblock) { 46995711cd5SPawel Dembicki case 0: 47095711cd5SPawel Dembicki return 1; 47195711cd5SPawel Dembicki } 47295711cd5SPawel Dembicki break; 47395711cd5SPawel Dembicki 47495711cd5SPawel Dembicki case VSC73XX_BLOCK_MII: 47595711cd5SPawel Dembicki case VSC73XX_BLOCK_CAPTURE: 47695711cd5SPawel Dembicki case VSC73XX_BLOCK_ARBITER: 47795711cd5SPawel Dembicki switch (subblock) { 47895711cd5SPawel Dembicki case 0 ... 1: 47995711cd5SPawel Dembicki return 1; 48095711cd5SPawel Dembicki } 48195711cd5SPawel Dembicki break; 48295711cd5SPawel Dembicki } 48395711cd5SPawel Dembicki 48495711cd5SPawel Dembicki return 0; 48595711cd5SPawel Dembicki } 48695711cd5SPawel Dembicki EXPORT_SYMBOL(vsc73xx_is_addr_valid); 48795711cd5SPawel Dembicki 48895711cd5SPawel Dembicki static int vsc73xx_read(struct vsc73xx *vsc, u8 block, u8 subblock, u8 reg, 48995711cd5SPawel Dembicki u32 *val) 49095711cd5SPawel Dembicki { 49195711cd5SPawel Dembicki return vsc->ops->read(vsc, block, subblock, reg, val); 49295711cd5SPawel Dembicki } 49395711cd5SPawel Dembicki 49495711cd5SPawel Dembicki static int vsc73xx_write(struct vsc73xx *vsc, u8 block, u8 subblock, u8 reg, 49595711cd5SPawel Dembicki u32 val) 49695711cd5SPawel Dembicki { 49795711cd5SPawel Dembicki return vsc->ops->write(vsc, block, subblock, reg, val); 49895711cd5SPawel Dembicki } 49995711cd5SPawel Dembicki 50095711cd5SPawel Dembicki static int vsc73xx_update_bits(struct vsc73xx *vsc, u8 block, u8 subblock, 50195711cd5SPawel Dembicki u8 reg, u32 mask, u32 val) 50295711cd5SPawel Dembicki { 50395711cd5SPawel Dembicki u32 tmp, orig; 50495711cd5SPawel Dembicki int ret; 50595711cd5SPawel Dembicki 50695711cd5SPawel Dembicki /* Same read-modify-write algorithm as e.g. regmap */ 50795711cd5SPawel Dembicki ret = vsc73xx_read(vsc, block, subblock, reg, &orig); 50895711cd5SPawel Dembicki if (ret) 50995711cd5SPawel Dembicki return ret; 51095711cd5SPawel Dembicki tmp = orig & ~mask; 51195711cd5SPawel Dembicki tmp |= val & mask; 51295711cd5SPawel Dembicki return vsc73xx_write(vsc, block, subblock, reg, tmp); 51395711cd5SPawel Dembicki } 51495711cd5SPawel Dembicki 51595711cd5SPawel Dembicki static int vsc73xx_detect(struct vsc73xx *vsc) 51695711cd5SPawel Dembicki { 51795711cd5SPawel Dembicki bool icpu_si_boot_en; 51895711cd5SPawel Dembicki bool icpu_pi_en; 51995711cd5SPawel Dembicki u32 val; 52095711cd5SPawel Dembicki u32 rev; 52195711cd5SPawel Dembicki int ret; 52295711cd5SPawel Dembicki u32 id; 52395711cd5SPawel Dembicki 52495711cd5SPawel Dembicki ret = vsc73xx_read(vsc, VSC73XX_BLOCK_SYSTEM, 0, 52595711cd5SPawel Dembicki VSC73XX_ICPU_MBOX_VAL, &val); 52695711cd5SPawel Dembicki if (ret) { 52795711cd5SPawel Dembicki dev_err(vsc->dev, "unable to read mailbox (%d)\n", ret); 52895711cd5SPawel Dembicki return ret; 52995711cd5SPawel Dembicki } 53095711cd5SPawel Dembicki 53195711cd5SPawel Dembicki if (val == 0xffffffff) { 5321da39ff0SPawel Dembicki dev_info(vsc->dev, "chip seems dead.\n"); 5331da39ff0SPawel Dembicki return -EAGAIN; 53495711cd5SPawel Dembicki } 53595711cd5SPawel Dembicki 53695711cd5SPawel Dembicki ret = vsc73xx_read(vsc, VSC73XX_BLOCK_SYSTEM, 0, 53795711cd5SPawel Dembicki VSC73XX_CHIPID, &val); 53895711cd5SPawel Dembicki if (ret) { 53995711cd5SPawel Dembicki dev_err(vsc->dev, "unable to read chip id (%d)\n", ret); 54095711cd5SPawel Dembicki return ret; 54195711cd5SPawel Dembicki } 54295711cd5SPawel Dembicki 54395711cd5SPawel Dembicki id = (val >> VSC73XX_CHIPID_ID_SHIFT) & 54495711cd5SPawel Dembicki VSC73XX_CHIPID_ID_MASK; 54595711cd5SPawel Dembicki switch (id) { 54695711cd5SPawel Dembicki case VSC73XX_CHIPID_ID_7385: 54795711cd5SPawel Dembicki case VSC73XX_CHIPID_ID_7388: 54895711cd5SPawel Dembicki case VSC73XX_CHIPID_ID_7395: 54995711cd5SPawel Dembicki case VSC73XX_CHIPID_ID_7398: 55095711cd5SPawel Dembicki break; 55195711cd5SPawel Dembicki default: 55295711cd5SPawel Dembicki dev_err(vsc->dev, "unsupported chip, id=%04x\n", id); 55395711cd5SPawel Dembicki return -ENODEV; 55495711cd5SPawel Dembicki } 55595711cd5SPawel Dembicki 55695711cd5SPawel Dembicki vsc->chipid = id; 55795711cd5SPawel Dembicki rev = (val >> VSC73XX_CHIPID_REV_SHIFT) & 55895711cd5SPawel Dembicki VSC73XX_CHIPID_REV_MASK; 55995711cd5SPawel Dembicki dev_info(vsc->dev, "VSC%04X (rev: %d) switch found\n", id, rev); 56095711cd5SPawel Dembicki 56195711cd5SPawel Dembicki ret = vsc73xx_read(vsc, VSC73XX_BLOCK_SYSTEM, 0, 56295711cd5SPawel Dembicki VSC73XX_ICPU_CTRL, &val); 56395711cd5SPawel Dembicki if (ret) { 56495711cd5SPawel Dembicki dev_err(vsc->dev, "unable to read iCPU control\n"); 56595711cd5SPawel Dembicki return ret; 56695711cd5SPawel Dembicki } 56795711cd5SPawel Dembicki 56895711cd5SPawel Dembicki /* The iCPU can always be used but can boot in different ways. 56995711cd5SPawel Dembicki * If it is initially disabled and has no external memory, 57095711cd5SPawel Dembicki * we are in control and can do whatever we like, else we 57195711cd5SPawel Dembicki * are probably in trouble (we need some way to communicate 57295711cd5SPawel Dembicki * with the running firmware) so we bail out for now. 57395711cd5SPawel Dembicki */ 57495711cd5SPawel Dembicki icpu_pi_en = !!(val & VSC73XX_ICPU_CTRL_ICPU_PI_EN); 57595711cd5SPawel Dembicki icpu_si_boot_en = !!(val & VSC73XX_ICPU_CTRL_BOOT_EN); 57695711cd5SPawel Dembicki if (icpu_si_boot_en && icpu_pi_en) { 57795711cd5SPawel Dembicki dev_err(vsc->dev, 57895711cd5SPawel Dembicki "iCPU enabled boots from SI, has external memory\n"); 57995711cd5SPawel Dembicki dev_err(vsc->dev, "no idea how to deal with this\n"); 58095711cd5SPawel Dembicki return -ENODEV; 58195711cd5SPawel Dembicki } 58295711cd5SPawel Dembicki if (icpu_si_boot_en && !icpu_pi_en) { 58395711cd5SPawel Dembicki dev_err(vsc->dev, 5841da39ff0SPawel Dembicki "iCPU enabled boots from PI/SI, no external memory\n"); 5851da39ff0SPawel Dembicki return -EAGAIN; 58695711cd5SPawel Dembicki } 58795711cd5SPawel Dembicki if (!icpu_si_boot_en && icpu_pi_en) { 58895711cd5SPawel Dembicki dev_err(vsc->dev, 58995711cd5SPawel Dembicki "iCPU enabled, boots from PI external memory\n"); 59095711cd5SPawel Dembicki dev_err(vsc->dev, "no idea how to deal with this\n"); 59195711cd5SPawel Dembicki return -ENODEV; 59295711cd5SPawel Dembicki } 59395711cd5SPawel Dembicki /* !icpu_si_boot_en && !cpu_pi_en */ 59495711cd5SPawel Dembicki dev_info(vsc->dev, "iCPU disabled, no external memory\n"); 59595711cd5SPawel Dembicki 59695711cd5SPawel Dembicki return 0; 59795711cd5SPawel Dembicki } 59895711cd5SPawel Dembicki 599fa63c643SPawel Dembicki static int vsc73xx_mdio_busy_check(struct vsc73xx *vsc) 600fa63c643SPawel Dembicki { 601fa63c643SPawel Dembicki int ret, err; 602fa63c643SPawel Dembicki u32 val; 603fa63c643SPawel Dembicki 604fa63c643SPawel Dembicki ret = read_poll_timeout(vsc73xx_read, err, 605fa63c643SPawel Dembicki err < 0 || !(val & VSC73XX_MII_STAT_BUSY), 606fa63c643SPawel Dembicki VSC73XX_MDIO_POLL_SLEEP_US, 607fa63c643SPawel Dembicki VSC73XX_POLL_TIMEOUT_US, false, vsc, 608fa63c643SPawel Dembicki VSC73XX_BLOCK_MII, VSC73XX_BLOCK_MII_INTERNAL, 609fa63c643SPawel Dembicki VSC73XX_MII_STAT, &val); 610fa63c643SPawel Dembicki if (ret) 611fa63c643SPawel Dembicki return ret; 612fa63c643SPawel Dembicki return err; 613fa63c643SPawel Dembicki } 614fa63c643SPawel Dembicki 61595711cd5SPawel Dembicki static int vsc73xx_phy_read(struct dsa_switch *ds, int phy, int regnum) 61695711cd5SPawel Dembicki { 61795711cd5SPawel Dembicki struct vsc73xx *vsc = ds->priv; 61895711cd5SPawel Dembicki u32 cmd; 61995711cd5SPawel Dembicki u32 val; 62095711cd5SPawel Dembicki int ret; 62195711cd5SPawel Dembicki 622fa63c643SPawel Dembicki ret = vsc73xx_mdio_busy_check(vsc); 623fa63c643SPawel Dembicki if (ret) 624fa63c643SPawel Dembicki return ret; 625fa63c643SPawel Dembicki 62695711cd5SPawel Dembicki /* Setting bit 26 means "read" */ 6272524d6c2SPawel Dembicki cmd = VSC73XX_MII_CMD_OPERATION | 6282524d6c2SPawel Dembicki FIELD_PREP(VSC73XX_MII_CMD_PHY_ADDR, phy) | 6292524d6c2SPawel Dembicki FIELD_PREP(VSC73XX_MII_CMD_PHY_REG, regnum); 6302524d6c2SPawel Dembicki ret = vsc73xx_write(vsc, VSC73XX_BLOCK_MII, VSC73XX_BLOCK_MII_INTERNAL, 6312524d6c2SPawel Dembicki VSC73XX_MII_CMD, cmd); 63295711cd5SPawel Dembicki if (ret) 63395711cd5SPawel Dembicki return ret; 634fa63c643SPawel Dembicki 635fa63c643SPawel Dembicki ret = vsc73xx_mdio_busy_check(vsc); 636fa63c643SPawel Dembicki if (ret) 637fa63c643SPawel Dembicki return ret; 638fa63c643SPawel Dembicki 6392524d6c2SPawel Dembicki ret = vsc73xx_read(vsc, VSC73XX_BLOCK_MII, VSC73XX_BLOCK_MII_INTERNAL, 6402524d6c2SPawel Dembicki VSC73XX_MII_DATA, &val); 64195711cd5SPawel Dembicki if (ret) 64295711cd5SPawel Dembicki return ret; 6432524d6c2SPawel Dembicki if (val & VSC73XX_MII_DATA_FAILURE) { 64495711cd5SPawel Dembicki dev_err(vsc->dev, "reading reg %02x from phy%d failed\n", 64595711cd5SPawel Dembicki regnum, phy); 64695711cd5SPawel Dembicki return -EIO; 64795711cd5SPawel Dembicki } 6482524d6c2SPawel Dembicki val &= VSC73XX_MII_DATA_READ_DATA; 64995711cd5SPawel Dembicki 65095711cd5SPawel Dembicki dev_dbg(vsc->dev, "read reg %02x from phy%d = %04x\n", 65195711cd5SPawel Dembicki regnum, phy, val); 65295711cd5SPawel Dembicki 65395711cd5SPawel Dembicki return val; 65495711cd5SPawel Dembicki } 65595711cd5SPawel Dembicki 65695711cd5SPawel Dembicki static int vsc73xx_phy_write(struct dsa_switch *ds, int phy, int regnum, 65795711cd5SPawel Dembicki u16 val) 65895711cd5SPawel Dembicki { 65995711cd5SPawel Dembicki struct vsc73xx *vsc = ds->priv; 66095711cd5SPawel Dembicki u32 cmd; 66195711cd5SPawel Dembicki int ret; 66295711cd5SPawel Dembicki 663fa63c643SPawel Dembicki ret = vsc73xx_mdio_busy_check(vsc); 664fa63c643SPawel Dembicki if (ret) 665fa63c643SPawel Dembicki return ret; 66695711cd5SPawel Dembicki 6672524d6c2SPawel Dembicki cmd = FIELD_PREP(VSC73XX_MII_CMD_PHY_ADDR, phy) | 6684d3d3559SJakub Kicinski FIELD_PREP(VSC73XX_MII_CMD_PHY_REG, regnum) | 6694d3d3559SJakub Kicinski FIELD_PREP(VSC73XX_MII_CMD_WRITE_DATA, val); 6702524d6c2SPawel Dembicki ret = vsc73xx_write(vsc, VSC73XX_BLOCK_MII, VSC73XX_BLOCK_MII_INTERNAL, 6712524d6c2SPawel Dembicki VSC73XX_MII_CMD, cmd); 67295711cd5SPawel Dembicki if (ret) 67395711cd5SPawel Dembicki return ret; 67495711cd5SPawel Dembicki 67595711cd5SPawel Dembicki dev_dbg(vsc->dev, "write %04x to reg %02x in phy%d\n", 67695711cd5SPawel Dembicki val, regnum, phy); 67795711cd5SPawel Dembicki return 0; 67895711cd5SPawel Dembicki } 67995711cd5SPawel Dembicki 68095711cd5SPawel Dembicki static enum dsa_tag_protocol vsc73xx_get_tag_protocol(struct dsa_switch *ds, 6814d776482SFlorian Fainelli int port, 6824d776482SFlorian Fainelli enum dsa_tag_protocol mp) 68395711cd5SPawel Dembicki { 68495711cd5SPawel Dembicki /* The switch internally uses a 8 byte header with length, 68595711cd5SPawel Dembicki * source port, tag, LPA and priority. This is supposedly 68695711cd5SPawel Dembicki * only accessible when operating the switch using the internal 68795711cd5SPawel Dembicki * CPU or with an external CPU mapping the device in, but not 68895711cd5SPawel Dembicki * when operating the switch over SPI and putting frames in/out 68995711cd5SPawel Dembicki * on port 6 (the CPU port). So far we must assume that we 69095711cd5SPawel Dembicki * cannot access the tag. (See "Internal frame header" section 69195711cd5SPawel Dembicki * 3.9.1 in the manual.) 69295711cd5SPawel Dembicki */ 693e3386ec4SPawel Dembicki return DSA_TAG_PROTO_VSC73XX_8021Q; 69495711cd5SPawel Dembicki } 69595711cd5SPawel Dembicki 6966b783dedSPawel Dembicki static int vsc73xx_wait_for_vlan_table_cmd(struct vsc73xx *vsc) 6976b783dedSPawel Dembicki { 6986b783dedSPawel Dembicki int ret, err; 6996b783dedSPawel Dembicki u32 val; 7006b783dedSPawel Dembicki 7016b783dedSPawel Dembicki ret = read_poll_timeout(vsc73xx_read, err, 7026b783dedSPawel Dembicki err < 0 || 7036b783dedSPawel Dembicki ((val & VSC73XX_VLANACCESS_VLAN_TBL_CMD_MASK) == 7046b783dedSPawel Dembicki VSC73XX_VLANACCESS_VLAN_TBL_CMD_IDLE), 7056b783dedSPawel Dembicki VSC73XX_POLL_SLEEP_US, VSC73XX_POLL_TIMEOUT_US, 7066b783dedSPawel Dembicki false, vsc, VSC73XX_BLOCK_ANALYZER, 7076b783dedSPawel Dembicki 0, VSC73XX_VLANACCESS, &val); 7086b783dedSPawel Dembicki if (ret) 7096b783dedSPawel Dembicki return ret; 7106b783dedSPawel Dembicki return err; 7116b783dedSPawel Dembicki } 7126b783dedSPawel Dembicki 7136b783dedSPawel Dembicki static int 7146b783dedSPawel Dembicki vsc73xx_read_vlan_table_entry(struct vsc73xx *vsc, u16 vid, u8 *portmap) 7156b783dedSPawel Dembicki { 7166b783dedSPawel Dembicki u32 val; 7176b783dedSPawel Dembicki int ret; 7186b783dedSPawel Dembicki 7196b783dedSPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANTIDX, vid); 7206b783dedSPawel Dembicki 7216b783dedSPawel Dembicki ret = vsc73xx_wait_for_vlan_table_cmd(vsc); 7226b783dedSPawel Dembicki if (ret) 7236b783dedSPawel Dembicki return ret; 7246b783dedSPawel Dembicki 7256b783dedSPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANACCESS, 7266b783dedSPawel Dembicki VSC73XX_VLANACCESS_VLAN_TBL_CMD_MASK, 7276b783dedSPawel Dembicki VSC73XX_VLANACCESS_VLAN_TBL_CMD_READ_ENTRY); 7286b783dedSPawel Dembicki 7296b783dedSPawel Dembicki ret = vsc73xx_wait_for_vlan_table_cmd(vsc); 7306b783dedSPawel Dembicki if (ret) 7316b783dedSPawel Dembicki return ret; 7326b783dedSPawel Dembicki 7336b783dedSPawel Dembicki vsc73xx_read(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANACCESS, &val); 7346b783dedSPawel Dembicki *portmap = (val & VSC73XX_VLANACCESS_VLAN_PORT_MASK) >> 7356b783dedSPawel Dembicki VSC73XX_VLANACCESS_VLAN_PORT_MASK_SHIFT; 7366b783dedSPawel Dembicki 7376b783dedSPawel Dembicki return 0; 7386b783dedSPawel Dembicki } 7396b783dedSPawel Dembicki 7406b783dedSPawel Dembicki static int 7416b783dedSPawel Dembicki vsc73xx_write_vlan_table_entry(struct vsc73xx *vsc, u16 vid, u8 portmap) 7426b783dedSPawel Dembicki { 7436b783dedSPawel Dembicki int ret; 7446b783dedSPawel Dembicki 7456b783dedSPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANTIDX, vid); 7466b783dedSPawel Dembicki 7476b783dedSPawel Dembicki ret = vsc73xx_wait_for_vlan_table_cmd(vsc); 7486b783dedSPawel Dembicki if (ret) 7496b783dedSPawel Dembicki return ret; 7506b783dedSPawel Dembicki 7516b783dedSPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANACCESS, 7526b783dedSPawel Dembicki VSC73XX_VLANACCESS_VLAN_TBL_CMD_MASK | 7536b783dedSPawel Dembicki VSC73XX_VLANACCESS_VLAN_SRC_CHECK | 7546b783dedSPawel Dembicki VSC73XX_VLANACCESS_VLAN_PORT_MASK, 7556b783dedSPawel Dembicki VSC73XX_VLANACCESS_VLAN_TBL_CMD_WRITE_ENTRY | 7566b783dedSPawel Dembicki VSC73XX_VLANACCESS_VLAN_SRC_CHECK | 7576b783dedSPawel Dembicki (portmap << VSC73XX_VLANACCESS_VLAN_PORT_MASK_SHIFT)); 7586b783dedSPawel Dembicki 7596b783dedSPawel Dembicki return vsc73xx_wait_for_vlan_table_cmd(vsc); 7606b783dedSPawel Dembicki } 7616b783dedSPawel Dembicki 7626b783dedSPawel Dembicki static int 7636b783dedSPawel Dembicki vsc73xx_update_vlan_table(struct vsc73xx *vsc, int port, u16 vid, bool set) 7646b783dedSPawel Dembicki { 7656b783dedSPawel Dembicki u8 portmap; 7666b783dedSPawel Dembicki int ret; 7676b783dedSPawel Dembicki 7686b783dedSPawel Dembicki ret = vsc73xx_read_vlan_table_entry(vsc, vid, &portmap); 7696b783dedSPawel Dembicki if (ret) 7706b783dedSPawel Dembicki return ret; 7716b783dedSPawel Dembicki 7726b783dedSPawel Dembicki if (set) 7736b783dedSPawel Dembicki portmap |= BIT(port); 7746b783dedSPawel Dembicki else 7756b783dedSPawel Dembicki portmap &= ~BIT(port); 7766b783dedSPawel Dembicki 7776b783dedSPawel Dembicki return vsc73xx_write_vlan_table_entry(vsc, vid, portmap); 7786b783dedSPawel Dembicki } 7796b783dedSPawel Dembicki 7803b91b032SPawel Dembicki static int vsc73xx_configure_rgmii_port_delay(struct dsa_switch *ds) 7813b91b032SPawel Dembicki { 7823b91b032SPawel Dembicki /* Keep 2.0 ns delay for backward complatibility */ 7833b91b032SPawel Dembicki u32 tx_delay = VSC73XX_GMIIDELAY_GMII0_GTXDELAY_2_0_NS; 7843b91b032SPawel Dembicki u32 rx_delay = VSC73XX_GMIIDELAY_GMII0_RXDELAY_2_0_NS; 7853b91b032SPawel Dembicki struct dsa_port *dp = dsa_to_port(ds, CPU_PORT); 7863b91b032SPawel Dembicki struct device_node *port_dn = dp->dn; 7873b91b032SPawel Dembicki struct vsc73xx *vsc = ds->priv; 7883b91b032SPawel Dembicki u32 delay; 7893b91b032SPawel Dembicki 7903b91b032SPawel Dembicki if (!of_property_read_u32(port_dn, "tx-internal-delay-ps", &delay)) { 7913b91b032SPawel Dembicki switch (delay) { 7923b91b032SPawel Dembicki case 0: 7933b91b032SPawel Dembicki tx_delay = VSC73XX_GMIIDELAY_GMII0_GTXDELAY_NONE; 7943b91b032SPawel Dembicki break; 7953b91b032SPawel Dembicki case 1400: 7963b91b032SPawel Dembicki tx_delay = VSC73XX_GMIIDELAY_GMII0_GTXDELAY_1_4_NS; 7973b91b032SPawel Dembicki break; 7983b91b032SPawel Dembicki case 1700: 7993b91b032SPawel Dembicki tx_delay = VSC73XX_GMIIDELAY_GMII0_GTXDELAY_1_7_NS; 8003b91b032SPawel Dembicki break; 8013b91b032SPawel Dembicki case 2000: 8023b91b032SPawel Dembicki break; 8033b91b032SPawel Dembicki default: 8043b91b032SPawel Dembicki dev_err(vsc->dev, 8053b91b032SPawel Dembicki "Unsupported RGMII Transmit Clock Delay\n"); 8063b91b032SPawel Dembicki return -EINVAL; 8073b91b032SPawel Dembicki } 8083b91b032SPawel Dembicki } else { 8093b91b032SPawel Dembicki dev_dbg(vsc->dev, 8103b91b032SPawel Dembicki "RGMII Transmit Clock Delay isn't configured, set to 2.0 ns\n"); 8113b91b032SPawel Dembicki } 8123b91b032SPawel Dembicki 8133b91b032SPawel Dembicki if (!of_property_read_u32(port_dn, "rx-internal-delay-ps", &delay)) { 8143b91b032SPawel Dembicki switch (delay) { 8153b91b032SPawel Dembicki case 0: 8163b91b032SPawel Dembicki rx_delay = VSC73XX_GMIIDELAY_GMII0_RXDELAY_NONE; 8173b91b032SPawel Dembicki break; 8183b91b032SPawel Dembicki case 1400: 8193b91b032SPawel Dembicki rx_delay = VSC73XX_GMIIDELAY_GMII0_RXDELAY_1_4_NS; 8203b91b032SPawel Dembicki break; 8213b91b032SPawel Dembicki case 1700: 8223b91b032SPawel Dembicki rx_delay = VSC73XX_GMIIDELAY_GMII0_RXDELAY_1_7_NS; 8233b91b032SPawel Dembicki break; 8243b91b032SPawel Dembicki case 2000: 8253b91b032SPawel Dembicki break; 8263b91b032SPawel Dembicki default: 8273b91b032SPawel Dembicki dev_err(vsc->dev, 8283b91b032SPawel Dembicki "Unsupported RGMII Receive Clock Delay value\n"); 8293b91b032SPawel Dembicki return -EINVAL; 8303b91b032SPawel Dembicki } 8313b91b032SPawel Dembicki } else { 8323b91b032SPawel Dembicki dev_dbg(vsc->dev, 8333b91b032SPawel Dembicki "RGMII Receive Clock Delay isn't configured, set to 2.0 ns\n"); 8343b91b032SPawel Dembicki } 8353b91b032SPawel Dembicki 8363b91b032SPawel Dembicki /* MII delay, set both GTX and RX delay */ 8373b91b032SPawel Dembicki return vsc73xx_write(vsc, VSC73XX_BLOCK_SYSTEM, 0, VSC73XX_GMIIDELAY, 8383b91b032SPawel Dembicki tx_delay | rx_delay); 8393b91b032SPawel Dembicki } 8403b91b032SPawel Dembicki 84195711cd5SPawel Dembicki static int vsc73xx_setup(struct dsa_switch *ds) 84295711cd5SPawel Dembicki { 84395711cd5SPawel Dembicki struct vsc73xx *vsc = ds->priv; 8448d5be2c4SPawel Dembicki int i, ret, val; 84595711cd5SPawel Dembicki 84695711cd5SPawel Dembicki dev_info(vsc->dev, "set up the switch\n"); 84795711cd5SPawel Dembicki 8486dfaaa27SPawel Dembicki ds->untag_bridge_pvid = true; 8496dfaaa27SPawel Dembicki ds->max_num_bridges = DSA_TAG_8021Q_MAX_NUM_BRIDGES; 850*075e3d30SPawel Dembicki ds->fdb_isolation = true; 8516dfaaa27SPawel Dembicki 85295711cd5SPawel Dembicki /* Issue RESET */ 85395711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_SYSTEM, 0, VSC73XX_GLORESET, 85495711cd5SPawel Dembicki VSC73XX_GLORESET_MASTER_RESET); 85595711cd5SPawel Dembicki usleep_range(125, 200); 85695711cd5SPawel Dembicki 85795711cd5SPawel Dembicki /* Initialize memory, initialize RAM bank 0..15 except 6 and 7 85895711cd5SPawel Dembicki * This sequence appears in the 85995711cd5SPawel Dembicki * VSC7385 SparX-G5 datasheet section 6.6.1 86095711cd5SPawel Dembicki * VSC7395 SparX-G5e datasheet section 6.6.1 86195711cd5SPawel Dembicki * "initialization sequence". 86295711cd5SPawel Dembicki * No explanation is given to the 0x1010400 magic number. 86395711cd5SPawel Dembicki */ 86495711cd5SPawel Dembicki for (i = 0; i <= 15; i++) { 86595711cd5SPawel Dembicki if (i != 6 && i != 7) { 86695711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MEMINIT, 86795711cd5SPawel Dembicki 2, 86895711cd5SPawel Dembicki 0, 0x1010400 + i); 86995711cd5SPawel Dembicki mdelay(1); 87095711cd5SPawel Dembicki } 87195711cd5SPawel Dembicki } 87295711cd5SPawel Dembicki mdelay(30); 87395711cd5SPawel Dembicki 87495711cd5SPawel Dembicki /* Clear MAC table */ 87595711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, 87695711cd5SPawel Dembicki VSC73XX_MACACCESS, 87795711cd5SPawel Dembicki VSC73XX_MACACCESS_CMD_CLEAR_TABLE); 87895711cd5SPawel Dembicki 8796b783dedSPawel Dembicki /* Set VLAN table to default values */ 88095711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, 88195711cd5SPawel Dembicki VSC73XX_VLANACCESS, 88295711cd5SPawel Dembicki VSC73XX_VLANACCESS_VLAN_TBL_CMD_CLEAR_TABLE); 88395711cd5SPawel Dembicki 88495711cd5SPawel Dembicki msleep(40); 88595711cd5SPawel Dembicki 88695711cd5SPawel Dembicki /* Use 20KiB buffers on all ports on VSC7395 88795711cd5SPawel Dembicki * The VSC7385 has 16KiB buffers and that is the 88895711cd5SPawel Dembicki * default if we don't set this up explicitly. 88995711cd5SPawel Dembicki * Port "31" is "all ports". 89095711cd5SPawel Dembicki */ 89195711cd5SPawel Dembicki if (IS_739X(vsc)) 89295711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 0x1f, 89395711cd5SPawel Dembicki VSC73XX_Q_MISC_CONF, 89495711cd5SPawel Dembicki VSC73XX_Q_MISC_CONF_EXTENT_MEM); 89595711cd5SPawel Dembicki 89695711cd5SPawel Dembicki /* Put all ports into reset until enabled */ 89795711cd5SPawel Dembicki for (i = 0; i < 7; i++) { 89895711cd5SPawel Dembicki if (i == 5) 89995711cd5SPawel Dembicki continue; 90095711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 4, 90195711cd5SPawel Dembicki VSC73XX_MAC_CFG, VSC73XX_MAC_CFG_RESET); 90295711cd5SPawel Dembicki } 90395711cd5SPawel Dembicki 9043b91b032SPawel Dembicki /* Configure RGMII delay */ 9053b91b032SPawel Dembicki ret = vsc73xx_configure_rgmii_port_delay(ds); 9063b91b032SPawel Dembicki if (ret) 9073b91b032SPawel Dembicki return ret; 9083b91b032SPawel Dembicki 9096b783dedSPawel Dembicki /* Ingess VLAN reception mask (table 145) */ 9106b783dedSPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANMASK, 9116b783dedSPawel Dembicki 0xff); 91295711cd5SPawel Dembicki /* IP multicast flood mask (table 144) */ 91395711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_IFLODMSK, 91495711cd5SPawel Dembicki 0xff); 91595711cd5SPawel Dembicki 91695711cd5SPawel Dembicki mdelay(50); 91795711cd5SPawel Dembicki 9188d5be2c4SPawel Dembicki /* Disable preamble and use maximum allowed clock for the internal 9198d5be2c4SPawel Dembicki * mdio bus, used for communication with internal PHYs only. 9208d5be2c4SPawel Dembicki */ 9218d5be2c4SPawel Dembicki val = VSC73XX_MII_MPRES_NOPREAMBLE | 9228d5be2c4SPawel Dembicki FIELD_PREP(VSC73XX_MII_MPRES_PRESCALEVAL, 9238d5be2c4SPawel Dembicki VSC73XX_MII_PRESCALEVAL_MIN); 9248d5be2c4SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MII, VSC73XX_BLOCK_MII_INTERNAL, 9258d5be2c4SPawel Dembicki VSC73XX_MII_MPRES, val); 9268d5be2c4SPawel Dembicki 92795711cd5SPawel Dembicki /* Release reset from the internal PHYs */ 92895711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_SYSTEM, 0, VSC73XX_GLORESET, 92995711cd5SPawel Dembicki VSC73XX_GLORESET_PHY_RESET); 93095711cd5SPawel Dembicki 93195711cd5SPawel Dembicki udelay(4); 93295711cd5SPawel Dembicki 9336b783dedSPawel Dembicki /* Clear VLAN table */ 9346b783dedSPawel Dembicki for (i = 0; i < VLAN_N_VID; i++) 9356b783dedSPawel Dembicki vsc73xx_write_vlan_table_entry(vsc, i, 0); 9366b783dedSPawel Dembicki 9376b783dedSPawel Dembicki INIT_LIST_HEAD(&vsc->vlans); 9386b783dedSPawel Dembicki 939e3386ec4SPawel Dembicki rtnl_lock(); 940e3386ec4SPawel Dembicki ret = dsa_tag_8021q_register(ds, htons(ETH_P_8021Q)); 941e3386ec4SPawel Dembicki rtnl_unlock(); 942e3386ec4SPawel Dembicki 943e3386ec4SPawel Dembicki return ret; 944e3386ec4SPawel Dembicki } 945e3386ec4SPawel Dembicki 946e3386ec4SPawel Dembicki static void vsc73xx_teardown(struct dsa_switch *ds) 947e3386ec4SPawel Dembicki { 948e3386ec4SPawel Dembicki rtnl_lock(); 949e3386ec4SPawel Dembicki dsa_tag_8021q_unregister(ds); 950e3386ec4SPawel Dembicki rtnl_unlock(); 95195711cd5SPawel Dembicki } 95295711cd5SPawel Dembicki 95395711cd5SPawel Dembicki static void vsc73xx_init_port(struct vsc73xx *vsc, int port) 95495711cd5SPawel Dembicki { 95595711cd5SPawel Dembicki u32 val; 95695711cd5SPawel Dembicki 95795711cd5SPawel Dembicki /* MAC configure, first reset the port and then write defaults */ 95895711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 95995711cd5SPawel Dembicki port, 96095711cd5SPawel Dembicki VSC73XX_MAC_CFG, 96195711cd5SPawel Dembicki VSC73XX_MAC_CFG_RESET); 96295711cd5SPawel Dembicki 96395711cd5SPawel Dembicki /* Take up the port in 1Gbit mode by default, this will be 96495711cd5SPawel Dembicki * augmented after auto-negotiation on the PHY-facing 96595711cd5SPawel Dembicki * ports. 96695711cd5SPawel Dembicki */ 96795711cd5SPawel Dembicki if (port == CPU_PORT) 96895711cd5SPawel Dembicki val = VSC73XX_MAC_CFG_1000M_F_RGMII; 96995711cd5SPawel Dembicki else 97095711cd5SPawel Dembicki val = VSC73XX_MAC_CFG_1000M_F_PHY; 97195711cd5SPawel Dembicki 97295711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 97395711cd5SPawel Dembicki port, 97495711cd5SPawel Dembicki VSC73XX_MAC_CFG, 97595711cd5SPawel Dembicki val | 97695711cd5SPawel Dembicki VSC73XX_MAC_CFG_TX_EN | 97795711cd5SPawel Dembicki VSC73XX_MAC_CFG_RX_EN); 97895711cd5SPawel Dembicki 97995711cd5SPawel Dembicki /* Flow control for the CPU port: 98095711cd5SPawel Dembicki * Use a zero delay pause frame when pause condition is left 98195711cd5SPawel Dembicki * Obey pause control frames 98295711cd5SPawel Dembicki */ 98395711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 98495711cd5SPawel Dembicki port, 98595711cd5SPawel Dembicki VSC73XX_FCCONF, 98695711cd5SPawel Dembicki VSC73XX_FCCONF_ZERO_PAUSE_EN | 98795711cd5SPawel Dembicki VSC73XX_FCCONF_FLOW_CTRL_OBEY); 98895711cd5SPawel Dembicki 98995711cd5SPawel Dembicki /* Issue pause control frames on PHY facing ports. 99095711cd5SPawel Dembicki * Allow early initiation of MAC transmission if the amount 99195711cd5SPawel Dembicki * of egress data is below 512 bytes on CPU port. 99295711cd5SPawel Dembicki * FIXME: enable 20KiB buffers? 99395711cd5SPawel Dembicki */ 99495711cd5SPawel Dembicki if (port == CPU_PORT) 99595711cd5SPawel Dembicki val = VSC73XX_Q_MISC_CONF_EARLY_TX_512; 99695711cd5SPawel Dembicki else 99795711cd5SPawel Dembicki val = VSC73XX_Q_MISC_CONF_MAC_PAUSE_MODE; 99895711cd5SPawel Dembicki val |= VSC73XX_Q_MISC_CONF_EXTENT_MEM; 99995711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 100095711cd5SPawel Dembicki port, 100195711cd5SPawel Dembicki VSC73XX_Q_MISC_CONF, 100295711cd5SPawel Dembicki val); 100395711cd5SPawel Dembicki 100495711cd5SPawel Dembicki /* Flow control MAC: a MAC address used in flow control frames */ 100595711cd5SPawel Dembicki val = (vsc->addr[5] << 16) | (vsc->addr[4] << 8) | (vsc->addr[3]); 100695711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 100795711cd5SPawel Dembicki port, 100895711cd5SPawel Dembicki VSC73XX_FCMACHI, 100995711cd5SPawel Dembicki val); 101095711cd5SPawel Dembicki val = (vsc->addr[2] << 16) | (vsc->addr[1] << 8) | (vsc->addr[0]); 101195711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 101295711cd5SPawel Dembicki port, 101395711cd5SPawel Dembicki VSC73XX_FCMACLO, 101495711cd5SPawel Dembicki val); 101595711cd5SPawel Dembicki 101695711cd5SPawel Dembicki /* Tell the categorizer to forward pause frames, not control 101795711cd5SPawel Dembicki * frame. Do not drop anything. 101895711cd5SPawel Dembicki */ 101995711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 102095711cd5SPawel Dembicki port, 102195711cd5SPawel Dembicki VSC73XX_CAT_DROP, 102295711cd5SPawel Dembicki VSC73XX_CAT_DROP_FWD_PAUSE_ENA); 102395711cd5SPawel Dembicki 102495711cd5SPawel Dembicki /* Clear all counters */ 102595711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 102695711cd5SPawel Dembicki port, VSC73XX_C_RX0, 0); 102795711cd5SPawel Dembicki } 102895711cd5SPawel Dembicki 102921fc3416SPawel Dembicki static void vsc73xx_reset_port(struct vsc73xx *vsc, int port, u32 initval) 103095711cd5SPawel Dembicki { 1031eb7e33d0SPawel Dembicki int ret, err; 103221fc3416SPawel Dembicki u32 val; 103395711cd5SPawel Dembicki 103495711cd5SPawel Dembicki /* Disable RX on this port */ 103595711cd5SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port, 103695711cd5SPawel Dembicki VSC73XX_MAC_CFG, 103795711cd5SPawel Dembicki VSC73XX_MAC_CFG_RX_EN, 0); 103895711cd5SPawel Dembicki 103995711cd5SPawel Dembicki /* Discard packets */ 104095711cd5SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, 0, 104195711cd5SPawel Dembicki VSC73XX_ARBDISC, BIT(port), BIT(port)); 104295711cd5SPawel Dembicki 104395711cd5SPawel Dembicki /* Wait until queue is empty */ 1044eb7e33d0SPawel Dembicki ret = read_poll_timeout(vsc73xx_read, err, 1045eb7e33d0SPawel Dembicki err < 0 || (val & BIT(port)), 1046eb7e33d0SPawel Dembicki VSC73XX_POLL_SLEEP_US, 1047eb7e33d0SPawel Dembicki VSC73XX_POLL_TIMEOUT_US, false, 1048eb7e33d0SPawel Dembicki vsc, VSC73XX_BLOCK_ARBITER, 0, 104995711cd5SPawel Dembicki VSC73XX_ARBEMPTY, &val); 1050eb7e33d0SPawel Dembicki if (ret) 105195711cd5SPawel Dembicki dev_err(vsc->dev, 105295711cd5SPawel Dembicki "timeout waiting for block arbiter\n"); 1053eb7e33d0SPawel Dembicki else if (err < 0) 1054eb7e33d0SPawel Dembicki dev_err(vsc->dev, "error reading arbiter\n"); 105595711cd5SPawel Dembicki 105695711cd5SPawel Dembicki /* Put this port into reset */ 105795711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, VSC73XX_MAC_CFG, 105821fc3416SPawel Dembicki VSC73XX_MAC_CFG_RESET | initval); 105921fc3416SPawel Dembicki } 106095711cd5SPawel Dembicki 106121fc3416SPawel Dembicki static void vsc73xx_mac_config(struct phylink_config *config, unsigned int mode, 106221fc3416SPawel Dembicki const struct phylink_link_state *state) 106321fc3416SPawel Dembicki { 106421fc3416SPawel Dembicki struct dsa_port *dp = dsa_phylink_to_port(config); 106521fc3416SPawel Dembicki struct vsc73xx *vsc = dp->ds->priv; 106621fc3416SPawel Dembicki int port = dp->index; 106721fc3416SPawel Dembicki 106821fc3416SPawel Dembicki /* Special handling of the CPU-facing port */ 106921fc3416SPawel Dembicki if (port == CPU_PORT) { 107021fc3416SPawel Dembicki /* Other ports are already initialized but not this one */ 107121fc3416SPawel Dembicki vsc73xx_init_port(vsc, CPU_PORT); 107221fc3416SPawel Dembicki /* Select the external port for this interface (EXT_PORT) 107321fc3416SPawel Dembicki * Enable the GMII GTX external clock 107421fc3416SPawel Dembicki * Use double data rate (DDR mode) 107521fc3416SPawel Dembicki */ 107621fc3416SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 107721fc3416SPawel Dembicki CPU_PORT, 107821fc3416SPawel Dembicki VSC73XX_ADVPORTM, 107921fc3416SPawel Dembicki VSC73XX_ADVPORTM_EXT_PORT | 108021fc3416SPawel Dembicki VSC73XX_ADVPORTM_ENA_GTX | 108121fc3416SPawel Dembicki VSC73XX_ADVPORTM_DDR_MODE); 108221fc3416SPawel Dembicki } 108321fc3416SPawel Dembicki } 108421fc3416SPawel Dembicki 108521fc3416SPawel Dembicki static void vsc73xx_mac_link_down(struct phylink_config *config, 108621fc3416SPawel Dembicki unsigned int mode, phy_interface_t interface) 108721fc3416SPawel Dembicki { 108821fc3416SPawel Dembicki struct dsa_port *dp = dsa_phylink_to_port(config); 108921fc3416SPawel Dembicki struct vsc73xx *vsc = dp->ds->priv; 109021fc3416SPawel Dembicki int port = dp->index; 109121fc3416SPawel Dembicki 109221fc3416SPawel Dembicki /* This routine is described in the datasheet (below ARBDISC register 109321fc3416SPawel Dembicki * description) 109421fc3416SPawel Dembicki */ 109521fc3416SPawel Dembicki vsc73xx_reset_port(vsc, port, 0); 109695711cd5SPawel Dembicki 109795711cd5SPawel Dembicki /* Allow backward dropping of frames from this port */ 109895711cd5SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, 0, 109995711cd5SPawel Dembicki VSC73XX_SBACKWDROP, BIT(port), BIT(port)); 110095711cd5SPawel Dembicki } 110195711cd5SPawel Dembicki 110221fc3416SPawel Dembicki static void vsc73xx_mac_link_up(struct phylink_config *config, 110321fc3416SPawel Dembicki struct phy_device *phy, unsigned int mode, 110421fc3416SPawel Dembicki phy_interface_t interface, int speed, 110521fc3416SPawel Dembicki int duplex, bool tx_pause, bool rx_pause) 110621fc3416SPawel Dembicki { 110721fc3416SPawel Dembicki struct dsa_port *dp = dsa_phylink_to_port(config); 110821fc3416SPawel Dembicki struct vsc73xx *vsc = dp->ds->priv; 110921fc3416SPawel Dembicki int port = dp->index; 111021fc3416SPawel Dembicki u32 val; 111121fc3416SPawel Dembicki u8 seed; 111295711cd5SPawel Dembicki 111321fc3416SPawel Dembicki if (speed == SPEED_1000) 111421fc3416SPawel Dembicki val = VSC73XX_MAC_CFG_GIGA_MODE | VSC73XX_MAC_CFG_TX_IPG_1000M; 111595711cd5SPawel Dembicki else 111621fc3416SPawel Dembicki val = VSC73XX_MAC_CFG_TX_IPG_100_10M; 111795711cd5SPawel Dembicki 111812af94b2SPawel Dembicki if (phy_interface_mode_is_rgmii(interface)) 111921fc3416SPawel Dembicki val |= VSC73XX_MAC_CFG_CLK_SEL_1000M; 112021fc3416SPawel Dembicki else 112121fc3416SPawel Dembicki val |= VSC73XX_MAC_CFG_CLK_SEL_EXT; 112221fc3416SPawel Dembicki 112321fc3416SPawel Dembicki if (duplex == DUPLEX_FULL) 112421fc3416SPawel Dembicki val |= VSC73XX_MAC_CFG_FDX; 112563796bc2SPawel Dembicki else 112663796bc2SPawel Dembicki /* In datasheet description ("Port Mode Procedure" in 5.6.2) 112763796bc2SPawel Dembicki * this bit is configured only for half duplex. 112863796bc2SPawel Dembicki */ 112963796bc2SPawel Dembicki val |= VSC73XX_MAC_CFG_WEXC_DIS; 113021fc3416SPawel Dembicki 113121fc3416SPawel Dembicki /* This routine is described in the datasheet (below ARBDISC register 113221fc3416SPawel Dembicki * description) 113321fc3416SPawel Dembicki */ 113421fc3416SPawel Dembicki vsc73xx_reset_port(vsc, port, val); 113521fc3416SPawel Dembicki 113621fc3416SPawel Dembicki /* Seed the port randomness with randomness */ 113721fc3416SPawel Dembicki get_random_bytes(&seed, 1); 113821fc3416SPawel Dembicki val |= seed << VSC73XX_MAC_CFG_SEED_OFFSET; 113921fc3416SPawel Dembicki val |= VSC73XX_MAC_CFG_SEED_LOAD; 11406b783dedSPawel Dembicki 11416b783dedSPawel Dembicki /* Those bits are responsible for MTU only. Kernel takes care about MTU, 11426b783dedSPawel Dembicki * let's enable +8 bytes frame length unconditionally. 11436b783dedSPawel Dembicki */ 11446b783dedSPawel Dembicki val |= VSC73XX_MAC_CFG_VLAN_AWR | VSC73XX_MAC_CFG_VLAN_DBLAWR; 11456b783dedSPawel Dembicki 114621fc3416SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, VSC73XX_MAC_CFG, val); 114721fc3416SPawel Dembicki 114821fc3416SPawel Dembicki /* Flow control for the PHY facing ports: 114921fc3416SPawel Dembicki * Use a zero delay pause frame when pause condition is left 115021fc3416SPawel Dembicki * Obey pause control frames 115121fc3416SPawel Dembicki * When generating pause frames, use 0xff as pause value 115221fc3416SPawel Dembicki */ 115321fc3416SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, VSC73XX_FCCONF, 115421fc3416SPawel Dembicki VSC73XX_FCCONF_ZERO_PAUSE_EN | 115521fc3416SPawel Dembicki VSC73XX_FCCONF_FLOW_CTRL_OBEY | 115621fc3416SPawel Dembicki 0xff); 115721fc3416SPawel Dembicki 115821fc3416SPawel Dembicki /* Accept packets again */ 115921fc3416SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, 0, 116021fc3416SPawel Dembicki VSC73XX_ARBDISC, BIT(port), 0); 116121fc3416SPawel Dembicki 116221fc3416SPawel Dembicki /* Disallow backward dropping of frames from this port */ 116321fc3416SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, 0, 116421fc3416SPawel Dembicki VSC73XX_SBACKWDROP, BIT(port), 0); 116521fc3416SPawel Dembicki 116621fc3416SPawel Dembicki /* Enable TX, RX, deassert reset, stop loading seed */ 116721fc3416SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port, 116821fc3416SPawel Dembicki VSC73XX_MAC_CFG, 116921fc3416SPawel Dembicki VSC73XX_MAC_CFG_RESET | VSC73XX_MAC_CFG_SEED_LOAD | 117021fc3416SPawel Dembicki VSC73XX_MAC_CFG_TX_EN | VSC73XX_MAC_CFG_RX_EN, 117121fc3416SPawel Dembicki VSC73XX_MAC_CFG_TX_EN | VSC73XX_MAC_CFG_RX_EN); 117295711cd5SPawel Dembicki } 117395711cd5SPawel Dembicki 11746b783dedSPawel Dembicki static bool vsc73xx_tag_8021q_active(struct dsa_port *dp) 11756b783dedSPawel Dembicki { 11766b783dedSPawel Dembicki return !dsa_port_is_vlan_filtering(dp); 11776b783dedSPawel Dembicki } 11786b783dedSPawel Dembicki 11796b783dedSPawel Dembicki static struct vsc73xx_bridge_vlan * 11806b783dedSPawel Dembicki vsc73xx_bridge_vlan_find(struct vsc73xx *vsc, u16 vid) 11816b783dedSPawel Dembicki { 11826b783dedSPawel Dembicki struct vsc73xx_bridge_vlan *vlan; 11836b783dedSPawel Dembicki 11846b783dedSPawel Dembicki list_for_each_entry(vlan, &vsc->vlans, list) 11856b783dedSPawel Dembicki if (vlan->vid == vid) 11866b783dedSPawel Dembicki return vlan; 11876b783dedSPawel Dembicki 11886b783dedSPawel Dembicki return NULL; 11896b783dedSPawel Dembicki } 11906b783dedSPawel Dembicki 11916b783dedSPawel Dembicki static void 11926b783dedSPawel Dembicki vsc73xx_bridge_vlan_remove_port(struct vsc73xx_bridge_vlan *vsc73xx_vlan, 11936b783dedSPawel Dembicki int port) 11946b783dedSPawel Dembicki { 11956b783dedSPawel Dembicki vsc73xx_vlan->portmask &= ~BIT(port); 11966b783dedSPawel Dembicki 11976b783dedSPawel Dembicki if (vsc73xx_vlan->portmask) 11986b783dedSPawel Dembicki return; 11996b783dedSPawel Dembicki 12006b783dedSPawel Dembicki list_del(&vsc73xx_vlan->list); 12016b783dedSPawel Dembicki kfree(vsc73xx_vlan); 12026b783dedSPawel Dembicki } 12036b783dedSPawel Dembicki 12046b783dedSPawel Dembicki static void vsc73xx_bridge_vlan_summary(struct vsc73xx *vsc, int port, 12056b783dedSPawel Dembicki struct vsc73xx_vlan_summary *summary, 12066b783dedSPawel Dembicki u16 ignored_vid) 12076b783dedSPawel Dembicki { 12086b783dedSPawel Dembicki size_t num_tagged = 0, num_untagged = 0; 12096b783dedSPawel Dembicki struct vsc73xx_bridge_vlan *vlan; 12106b783dedSPawel Dembicki 12116b783dedSPawel Dembicki list_for_each_entry(vlan, &vsc->vlans, list) { 12126b783dedSPawel Dembicki if (!(vlan->portmask & BIT(port)) || vlan->vid == ignored_vid) 12136b783dedSPawel Dembicki continue; 12146b783dedSPawel Dembicki 12156b783dedSPawel Dembicki if (vlan->untagged & BIT(port)) 12166b783dedSPawel Dembicki num_untagged++; 12176b783dedSPawel Dembicki else 12186b783dedSPawel Dembicki num_tagged++; 12196b783dedSPawel Dembicki } 12206b783dedSPawel Dembicki 12216b783dedSPawel Dembicki summary->num_untagged = num_untagged; 12226b783dedSPawel Dembicki summary->num_tagged = num_tagged; 12236b783dedSPawel Dembicki } 12246b783dedSPawel Dembicki 12256b783dedSPawel Dembicki static u16 vsc73xx_find_first_vlan_untagged(struct vsc73xx *vsc, int port) 12266b783dedSPawel Dembicki { 12276b783dedSPawel Dembicki struct vsc73xx_bridge_vlan *vlan; 12286b783dedSPawel Dembicki 12296b783dedSPawel Dembicki list_for_each_entry(vlan, &vsc->vlans, list) 12306b783dedSPawel Dembicki if ((vlan->portmask & BIT(port)) && 12316b783dedSPawel Dembicki (vlan->untagged & BIT(port))) 12326b783dedSPawel Dembicki return vlan->vid; 12336b783dedSPawel Dembicki 12346b783dedSPawel Dembicki return VLAN_N_VID; 12356b783dedSPawel Dembicki } 12366b783dedSPawel Dembicki 12376b783dedSPawel Dembicki static int vsc73xx_set_vlan_conf(struct vsc73xx *vsc, int port, 12386b783dedSPawel Dembicki enum vsc73xx_port_vlan_conf port_vlan_conf) 12396b783dedSPawel Dembicki { 12406b783dedSPawel Dembicki u32 val = 0; 12416b783dedSPawel Dembicki int ret; 12426b783dedSPawel Dembicki 12436b783dedSPawel Dembicki if (port_vlan_conf == VSC73XX_VLAN_IGNORE) 12446b783dedSPawel Dembicki val = VSC73XX_CAT_VLAN_MISC_VLAN_TCI_IGNORE_ENA | 12456b783dedSPawel Dembicki VSC73XX_CAT_VLAN_MISC_VLAN_KEEP_TAG_ENA; 12466b783dedSPawel Dembicki 12476b783dedSPawel Dembicki ret = vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port, 12486b783dedSPawel Dembicki VSC73XX_CAT_VLAN_MISC, 12496b783dedSPawel Dembicki VSC73XX_CAT_VLAN_MISC_VLAN_TCI_IGNORE_ENA | 12506b783dedSPawel Dembicki VSC73XX_CAT_VLAN_MISC_VLAN_KEEP_TAG_ENA, val); 12516b783dedSPawel Dembicki if (ret) 12526b783dedSPawel Dembicki return ret; 12536b783dedSPawel Dembicki 12546b783dedSPawel Dembicki val = (port_vlan_conf == VSC73XX_VLAN_FILTER) ? 12556b783dedSPawel Dembicki VSC73XX_TXUPDCFG_TX_INSERT_TAG : 0; 12566b783dedSPawel Dembicki 12576b783dedSPawel Dembicki return vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port, 12586b783dedSPawel Dembicki VSC73XX_TXUPDCFG, 12596b783dedSPawel Dembicki VSC73XX_TXUPDCFG_TX_INSERT_TAG, val); 12606b783dedSPawel Dembicki } 12616b783dedSPawel Dembicki 12626b783dedSPawel Dembicki /** 12636b783dedSPawel Dembicki * vsc73xx_vlan_commit_conf - Update VLAN configuration of a port 12646b783dedSPawel Dembicki * @vsc: Switch private data structure 12656b783dedSPawel Dembicki * @port: Port index on which to operate 12666b783dedSPawel Dembicki * 12676b783dedSPawel Dembicki * Update the VLAN behavior of a port to make sure that when it is under 12686b783dedSPawel Dembicki * a VLAN filtering bridge, the port is either filtering with tag 12696b783dedSPawel Dembicki * preservation, or filtering with all VLANs egress-untagged. Otherwise, 12706b783dedSPawel Dembicki * the port ignores VLAN tags from packets and applies the port-based 12716b783dedSPawel Dembicki * VID. 12726b783dedSPawel Dembicki * 12736b783dedSPawel Dembicki * Must be called when changes are made to: 12746b783dedSPawel Dembicki * - the bridge VLAN filtering state of the port 12756b783dedSPawel Dembicki * - the number or attributes of VLANs from the bridge VLAN table, 12766b783dedSPawel Dembicki * while the port is currently VLAN-aware 12776b783dedSPawel Dembicki * 12786b783dedSPawel Dembicki * Return: 0 on success, or negative errno on error. 12796b783dedSPawel Dembicki */ 12806b783dedSPawel Dembicki static int vsc73xx_vlan_commit_conf(struct vsc73xx *vsc, int port) 12816b783dedSPawel Dembicki { 12826b783dedSPawel Dembicki enum vsc73xx_port_vlan_conf port_vlan_conf = VSC73XX_VLAN_IGNORE; 12836b783dedSPawel Dembicki struct dsa_port *dp = dsa_to_port(vsc->ds, port); 12846b783dedSPawel Dembicki 12856b783dedSPawel Dembicki if (port == CPU_PORT) { 12866b783dedSPawel Dembicki port_vlan_conf = VSC73XX_VLAN_FILTER; 12876b783dedSPawel Dembicki } else if (dsa_port_is_vlan_filtering(dp)) { 12886b783dedSPawel Dembicki struct vsc73xx_vlan_summary summary; 12896b783dedSPawel Dembicki 12906b783dedSPawel Dembicki port_vlan_conf = VSC73XX_VLAN_FILTER; 12916b783dedSPawel Dembicki 12926b783dedSPawel Dembicki vsc73xx_bridge_vlan_summary(vsc, port, &summary, VLAN_N_VID); 12936b783dedSPawel Dembicki if (summary.num_tagged == 0) 12946b783dedSPawel Dembicki port_vlan_conf = VSC73XX_VLAN_FILTER_UNTAG_ALL; 12956b783dedSPawel Dembicki } 12966b783dedSPawel Dembicki 12976b783dedSPawel Dembicki return vsc73xx_set_vlan_conf(vsc, port, port_vlan_conf); 12986b783dedSPawel Dembicki } 12996b783dedSPawel Dembicki 13006b783dedSPawel Dembicki static int 13016b783dedSPawel Dembicki vsc73xx_vlan_change_untagged(struct vsc73xx *vsc, int port, u16 vid, bool set) 13026b783dedSPawel Dembicki { 13036b783dedSPawel Dembicki u32 val = 0; 13046b783dedSPawel Dembicki 13056b783dedSPawel Dembicki if (set) 13066b783dedSPawel Dembicki val = VSC73XX_TXUPDCFG_TX_UNTAGGED_VID_ENA | 13076b783dedSPawel Dembicki ((vid << VSC73XX_TXUPDCFG_TX_UNTAGGED_VID_SHIFT) & 13086b783dedSPawel Dembicki VSC73XX_TXUPDCFG_TX_UNTAGGED_VID); 13096b783dedSPawel Dembicki 13106b783dedSPawel Dembicki return vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port, 13116b783dedSPawel Dembicki VSC73XX_TXUPDCFG, 13126b783dedSPawel Dembicki VSC73XX_TXUPDCFG_TX_UNTAGGED_VID_ENA | 13136b783dedSPawel Dembicki VSC73XX_TXUPDCFG_TX_UNTAGGED_VID, val); 13146b783dedSPawel Dembicki } 13156b783dedSPawel Dembicki 13166b783dedSPawel Dembicki /** 13176b783dedSPawel Dembicki * vsc73xx_vlan_commit_untagged - Update native VLAN of a port 13186b783dedSPawel Dembicki * @vsc: Switch private data structure 13196b783dedSPawel Dembicki * @port: Port index on which to operate 13206b783dedSPawel Dembicki * 13216b783dedSPawel Dembicki * Update the native VLAN of a port (the one VLAN which is transmitted 13226b783dedSPawel Dembicki * as egress-tagged on a trunk port) when port is in VLAN filtering mode and 13236b783dedSPawel Dembicki * only one untagged vid is configured. 13246b783dedSPawel Dembicki * In other cases no need to configure it because switch can untag all vlans on 13256b783dedSPawel Dembicki * the port. 13266b783dedSPawel Dembicki * 13276b783dedSPawel Dembicki * Return: 0 on success, or negative errno on error. 13286b783dedSPawel Dembicki */ 13296b783dedSPawel Dembicki static int vsc73xx_vlan_commit_untagged(struct vsc73xx *vsc, int port) 13306b783dedSPawel Dembicki { 13316b783dedSPawel Dembicki struct dsa_port *dp = dsa_to_port(vsc->ds, port); 13326b783dedSPawel Dembicki struct vsc73xx_vlan_summary summary; 13336b783dedSPawel Dembicki u16 vid = 0; 13346b783dedSPawel Dembicki bool valid; 13356b783dedSPawel Dembicki 13366b783dedSPawel Dembicki if (!dsa_port_is_vlan_filtering(dp)) 13376b783dedSPawel Dembicki /* Port is configured to untag all vlans in that case. 13386b783dedSPawel Dembicki * No need to commit untagged config change. 13396b783dedSPawel Dembicki */ 13406b783dedSPawel Dembicki return 0; 13416b783dedSPawel Dembicki 13426b783dedSPawel Dembicki vsc73xx_bridge_vlan_summary(vsc, port, &summary, VLAN_N_VID); 13436b783dedSPawel Dembicki 13446b783dedSPawel Dembicki if (summary.num_untagged > 1) 13456b783dedSPawel Dembicki /* Port must untag all vlans in that case. 13466b783dedSPawel Dembicki * No need to commit untagged config change. 13476b783dedSPawel Dembicki */ 13486b783dedSPawel Dembicki return 0; 13496b783dedSPawel Dembicki 13506b783dedSPawel Dembicki valid = (summary.num_untagged == 1); 13516b783dedSPawel Dembicki if (valid) 13526b783dedSPawel Dembicki vid = vsc73xx_find_first_vlan_untagged(vsc, port); 13536b783dedSPawel Dembicki 13546b783dedSPawel Dembicki return vsc73xx_vlan_change_untagged(vsc, port, vid, valid); 13556b783dedSPawel Dembicki } 13566b783dedSPawel Dembicki 13576b783dedSPawel Dembicki static int 13586b783dedSPawel Dembicki vsc73xx_vlan_change_pvid(struct vsc73xx *vsc, int port, u16 vid, bool set) 13596b783dedSPawel Dembicki { 13606b783dedSPawel Dembicki u32 val = 0; 13616b783dedSPawel Dembicki int ret; 13626b783dedSPawel Dembicki 13636b783dedSPawel Dembicki val = set ? 0 : VSC73XX_CAT_DROP_UNTAGGED_ENA; 13646b783dedSPawel Dembicki 13656b783dedSPawel Dembicki ret = vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port, 13666b783dedSPawel Dembicki VSC73XX_CAT_DROP, 13676b783dedSPawel Dembicki VSC73XX_CAT_DROP_UNTAGGED_ENA, val); 13686b783dedSPawel Dembicki if (!set || ret) 13696b783dedSPawel Dembicki return ret; 13706b783dedSPawel Dembicki 13716b783dedSPawel Dembicki return vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port, 13726b783dedSPawel Dembicki VSC73XX_CAT_PORT_VLAN, 13736b783dedSPawel Dembicki VSC73XX_CAT_PORT_VLAN_VLAN_VID, 13746b783dedSPawel Dembicki vid & VSC73XX_CAT_PORT_VLAN_VLAN_VID); 13756b783dedSPawel Dembicki } 13766b783dedSPawel Dembicki 13776b783dedSPawel Dembicki /** 13786b783dedSPawel Dembicki * vsc73xx_vlan_commit_pvid - Update port-based default VLAN of a port 13796b783dedSPawel Dembicki * @vsc: Switch private data structure 13806b783dedSPawel Dembicki * @port: Port index on which to operate 13816b783dedSPawel Dembicki * 13826b783dedSPawel Dembicki * Update the PVID of a port so that it follows either the bridge PVID 13836b783dedSPawel Dembicki * configuration, when the bridge is currently VLAN-aware, or the PVID 13846b783dedSPawel Dembicki * from tag_8021q, when the port is standalone or under a VLAN-unaware 13856b783dedSPawel Dembicki * bridge. A port with no PVID drops all untagged and VID 0 tagged 13866b783dedSPawel Dembicki * traffic. 13876b783dedSPawel Dembicki * 13886b783dedSPawel Dembicki * Must be called when changes are made to: 13896b783dedSPawel Dembicki * - the bridge VLAN filtering state of the port 13906b783dedSPawel Dembicki * - the number or attributes of VLANs from the bridge VLAN table, 13916b783dedSPawel Dembicki * while the port is currently VLAN-aware 13926b783dedSPawel Dembicki * 13936b783dedSPawel Dembicki * Return: 0 on success, or negative errno on error. 13946b783dedSPawel Dembicki */ 13956b783dedSPawel Dembicki static int vsc73xx_vlan_commit_pvid(struct vsc73xx *vsc, int port) 13966b783dedSPawel Dembicki { 13976b783dedSPawel Dembicki struct vsc73xx_portinfo *portinfo = &vsc->portinfo[port]; 13986b783dedSPawel Dembicki bool valid = portinfo->pvid_tag_8021q_configured; 13996b783dedSPawel Dembicki struct dsa_port *dp = dsa_to_port(vsc->ds, port); 14006b783dedSPawel Dembicki u16 vid = portinfo->pvid_tag_8021q; 14016b783dedSPawel Dembicki 14026b783dedSPawel Dembicki if (dsa_port_is_vlan_filtering(dp)) { 14036b783dedSPawel Dembicki vid = portinfo->pvid_vlan_filtering; 14046b783dedSPawel Dembicki valid = portinfo->pvid_vlan_filtering_configured; 14056b783dedSPawel Dembicki } 14066b783dedSPawel Dembicki 14076b783dedSPawel Dembicki return vsc73xx_vlan_change_pvid(vsc, port, vid, valid); 14086b783dedSPawel Dembicki } 14096b783dedSPawel Dembicki 14106b783dedSPawel Dembicki static int vsc73xx_vlan_commit_settings(struct vsc73xx *vsc, int port) 14116b783dedSPawel Dembicki { 14126b783dedSPawel Dembicki int ret; 14136b783dedSPawel Dembicki 14146b783dedSPawel Dembicki ret = vsc73xx_vlan_commit_untagged(vsc, port); 14156b783dedSPawel Dembicki if (ret) 14166b783dedSPawel Dembicki return ret; 14176b783dedSPawel Dembicki 14186b783dedSPawel Dembicki ret = vsc73xx_vlan_commit_pvid(vsc, port); 14196b783dedSPawel Dembicki if (ret) 14206b783dedSPawel Dembicki return ret; 14216b783dedSPawel Dembicki 14226b783dedSPawel Dembicki return vsc73xx_vlan_commit_conf(vsc, port); 14236b783dedSPawel Dembicki } 14246b783dedSPawel Dembicki 142595711cd5SPawel Dembicki static int vsc73xx_port_enable(struct dsa_switch *ds, int port, 142695711cd5SPawel Dembicki struct phy_device *phy) 142795711cd5SPawel Dembicki { 142895711cd5SPawel Dembicki struct vsc73xx *vsc = ds->priv; 142995711cd5SPawel Dembicki 143095711cd5SPawel Dembicki dev_info(vsc->dev, "enable port %d\n", port); 143195711cd5SPawel Dembicki vsc73xx_init_port(vsc, port); 143295711cd5SPawel Dembicki 14336b783dedSPawel Dembicki return vsc73xx_vlan_commit_settings(vsc, port); 143495711cd5SPawel Dembicki } 143595711cd5SPawel Dembicki 143695711cd5SPawel Dembicki static void vsc73xx_port_disable(struct dsa_switch *ds, int port) 143795711cd5SPawel Dembicki { 143895711cd5SPawel Dembicki struct vsc73xx *vsc = ds->priv; 143995711cd5SPawel Dembicki 144095711cd5SPawel Dembicki /* Just put the port into reset */ 144195711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, 144295711cd5SPawel Dembicki VSC73XX_MAC_CFG, VSC73XX_MAC_CFG_RESET); 144395711cd5SPawel Dembicki } 144495711cd5SPawel Dembicki 144595711cd5SPawel Dembicki static const struct vsc73xx_counter * 144695711cd5SPawel Dembicki vsc73xx_find_counter(struct vsc73xx *vsc, 144795711cd5SPawel Dembicki u8 counter, 144895711cd5SPawel Dembicki bool tx) 144995711cd5SPawel Dembicki { 145095711cd5SPawel Dembicki const struct vsc73xx_counter *cnts; 145195711cd5SPawel Dembicki int num_cnts; 145295711cd5SPawel Dembicki int i; 145395711cd5SPawel Dembicki 145495711cd5SPawel Dembicki if (tx) { 145595711cd5SPawel Dembicki cnts = vsc73xx_tx_counters; 145695711cd5SPawel Dembicki num_cnts = ARRAY_SIZE(vsc73xx_tx_counters); 145795711cd5SPawel Dembicki } else { 145895711cd5SPawel Dembicki cnts = vsc73xx_rx_counters; 145995711cd5SPawel Dembicki num_cnts = ARRAY_SIZE(vsc73xx_rx_counters); 146095711cd5SPawel Dembicki } 146195711cd5SPawel Dembicki 146295711cd5SPawel Dembicki for (i = 0; i < num_cnts; i++) { 146395711cd5SPawel Dembicki const struct vsc73xx_counter *cnt; 146495711cd5SPawel Dembicki 146595711cd5SPawel Dembicki cnt = &cnts[i]; 146695711cd5SPawel Dembicki if (cnt->counter == counter) 146795711cd5SPawel Dembicki return cnt; 146895711cd5SPawel Dembicki } 146995711cd5SPawel Dembicki 147095711cd5SPawel Dembicki return NULL; 147195711cd5SPawel Dembicki } 147295711cd5SPawel Dembicki 147395711cd5SPawel Dembicki static void vsc73xx_get_strings(struct dsa_switch *ds, int port, u32 stringset, 147495711cd5SPawel Dembicki uint8_t *data) 147595711cd5SPawel Dembicki { 147695711cd5SPawel Dembicki const struct vsc73xx_counter *cnt; 147795711cd5SPawel Dembicki struct vsc73xx *vsc = ds->priv; 147895711cd5SPawel Dembicki u8 indices[6]; 1479e3bbab47SJustin Stitt u8 *buf = data; 1480e3bbab47SJustin Stitt int i; 148195711cd5SPawel Dembicki u32 val; 148295711cd5SPawel Dembicki int ret; 148395711cd5SPawel Dembicki 148495711cd5SPawel Dembicki if (stringset != ETH_SS_STATS) 148595711cd5SPawel Dembicki return; 148695711cd5SPawel Dembicki 148795711cd5SPawel Dembicki ret = vsc73xx_read(vsc, VSC73XX_BLOCK_MAC, port, 148895711cd5SPawel Dembicki VSC73XX_C_CFG, &val); 148995711cd5SPawel Dembicki if (ret) 149095711cd5SPawel Dembicki return; 149195711cd5SPawel Dembicki 149295711cd5SPawel Dembicki indices[0] = (val & 0x1f); /* RX counter 0 */ 149395711cd5SPawel Dembicki indices[1] = ((val >> 5) & 0x1f); /* RX counter 1 */ 149495711cd5SPawel Dembicki indices[2] = ((val >> 10) & 0x1f); /* RX counter 2 */ 149595711cd5SPawel Dembicki indices[3] = ((val >> 16) & 0x1f); /* TX counter 0 */ 149695711cd5SPawel Dembicki indices[4] = ((val >> 21) & 0x1f); /* TX counter 1 */ 149795711cd5SPawel Dembicki indices[5] = ((val >> 26) & 0x1f); /* TX counter 2 */ 149895711cd5SPawel Dembicki 149995711cd5SPawel Dembicki /* The first counters is the RX octets */ 1500e403cfffSjustinstitt@google.com ethtool_puts(&buf, "RxEtherStatsOctets"); 150195711cd5SPawel Dembicki 150295711cd5SPawel Dembicki /* Each port supports recording 3 RX counters and 3 TX counters, 150395711cd5SPawel Dembicki * figure out what counters we use in this set-up and return the 150495711cd5SPawel Dembicki * names of them. The hardware default counters will be number of 150595711cd5SPawel Dembicki * packets on RX/TX, combined broadcast+multicast packets RX/TX and 150695711cd5SPawel Dembicki * total error packets RX/TX. 150795711cd5SPawel Dembicki */ 150895711cd5SPawel Dembicki for (i = 0; i < 3; i++) { 150995711cd5SPawel Dembicki cnt = vsc73xx_find_counter(vsc, indices[i], false); 1510e403cfffSjustinstitt@google.com ethtool_puts(&buf, cnt ? cnt->name : ""); 151195711cd5SPawel Dembicki } 151295711cd5SPawel Dembicki 151395711cd5SPawel Dembicki /* TX stats begins with the number of TX octets */ 1514e403cfffSjustinstitt@google.com ethtool_puts(&buf, "TxEtherStatsOctets"); 151595711cd5SPawel Dembicki 151695711cd5SPawel Dembicki for (i = 3; i < 6; i++) { 151795711cd5SPawel Dembicki cnt = vsc73xx_find_counter(vsc, indices[i], true); 1518e403cfffSjustinstitt@google.com ethtool_puts(&buf, cnt ? cnt->name : ""); 1519e3bbab47SJustin Stitt 152095711cd5SPawel Dembicki } 152195711cd5SPawel Dembicki } 152295711cd5SPawel Dembicki 152395711cd5SPawel Dembicki static int vsc73xx_get_sset_count(struct dsa_switch *ds, int port, int sset) 152495711cd5SPawel Dembicki { 152595711cd5SPawel Dembicki /* We only support SS_STATS */ 152695711cd5SPawel Dembicki if (sset != ETH_SS_STATS) 152795711cd5SPawel Dembicki return 0; 152895711cd5SPawel Dembicki /* RX and TX packets, then 3 RX counters, 3 TX counters */ 152995711cd5SPawel Dembicki return 8; 153095711cd5SPawel Dembicki } 153195711cd5SPawel Dembicki 153295711cd5SPawel Dembicki static void vsc73xx_get_ethtool_stats(struct dsa_switch *ds, int port, 153395711cd5SPawel Dembicki uint64_t *data) 153495711cd5SPawel Dembicki { 153595711cd5SPawel Dembicki struct vsc73xx *vsc = ds->priv; 153695711cd5SPawel Dembicki u8 regs[] = { 153795711cd5SPawel Dembicki VSC73XX_RXOCT, 153895711cd5SPawel Dembicki VSC73XX_C_RX0, 153995711cd5SPawel Dembicki VSC73XX_C_RX1, 154095711cd5SPawel Dembicki VSC73XX_C_RX2, 154195711cd5SPawel Dembicki VSC73XX_TXOCT, 154295711cd5SPawel Dembicki VSC73XX_C_TX0, 154395711cd5SPawel Dembicki VSC73XX_C_TX1, 154495711cd5SPawel Dembicki VSC73XX_C_TX2, 154595711cd5SPawel Dembicki }; 154695711cd5SPawel Dembicki u32 val; 154795711cd5SPawel Dembicki int ret; 154895711cd5SPawel Dembicki int i; 154995711cd5SPawel Dembicki 155095711cd5SPawel Dembicki for (i = 0; i < ARRAY_SIZE(regs); i++) { 155195711cd5SPawel Dembicki ret = vsc73xx_read(vsc, VSC73XX_BLOCK_MAC, port, 155295711cd5SPawel Dembicki regs[i], &val); 155395711cd5SPawel Dembicki if (ret) { 155495711cd5SPawel Dembicki dev_err(vsc->dev, "error reading counter %d\n", i); 155595711cd5SPawel Dembicki return; 155695711cd5SPawel Dembicki } 155795711cd5SPawel Dembicki data[i] = val; 155895711cd5SPawel Dembicki } 155995711cd5SPawel Dembicki } 156095711cd5SPawel Dembicki 1561fb77ffc6SVladimir Oltean static int vsc73xx_change_mtu(struct dsa_switch *ds, int port, int new_mtu) 1562fb77ffc6SVladimir Oltean { 1563fb77ffc6SVladimir Oltean struct vsc73xx *vsc = ds->priv; 1564fb77ffc6SVladimir Oltean 1565fb77ffc6SVladimir Oltean return vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, 15663cf62c81SPawel Dembicki VSC73XX_MAXLEN, new_mtu + ETH_HLEN + ETH_FCS_LEN); 1567fb77ffc6SVladimir Oltean } 1568fb77ffc6SVladimir Oltean 1569fb77ffc6SVladimir Oltean /* According to application not "VSC7398 Jumbo Frames" setting 15703cf62c81SPawel Dembicki * up the frame size to 9.6 KB does not affect the performance on standard 1571fb77ffc6SVladimir Oltean * frames. It is clear from the application note that 1572fb77ffc6SVladimir Oltean * "9.6 kilobytes" == 9600 bytes. 1573fb77ffc6SVladimir Oltean */ 1574fb77ffc6SVladimir Oltean static int vsc73xx_get_max_mtu(struct dsa_switch *ds, int port) 1575fb77ffc6SVladimir Oltean { 15763cf62c81SPawel Dembicki return 9600 - ETH_HLEN - ETH_FCS_LEN; 1577fb77ffc6SVladimir Oltean } 1578fb77ffc6SVladimir Oltean 1579a026809cSRussell King (Oracle) static void vsc73xx_phylink_get_caps(struct dsa_switch *dsa, int port, 1580a026809cSRussell King (Oracle) struct phylink_config *config) 1581a026809cSRussell King (Oracle) { 1582a026809cSRussell King (Oracle) unsigned long *interfaces = config->supported_interfaces; 1583a026809cSRussell King (Oracle) 1584a026809cSRussell King (Oracle) if (port == 5) 1585a026809cSRussell King (Oracle) return; 1586a026809cSRussell King (Oracle) 1587a026809cSRussell King (Oracle) if (port == CPU_PORT) { 1588a026809cSRussell King (Oracle) __set_bit(PHY_INTERFACE_MODE_MII, interfaces); 1589a026809cSRussell King (Oracle) __set_bit(PHY_INTERFACE_MODE_REVMII, interfaces); 1590a026809cSRussell King (Oracle) __set_bit(PHY_INTERFACE_MODE_GMII, interfaces); 1591a026809cSRussell King (Oracle) __set_bit(PHY_INTERFACE_MODE_RGMII, interfaces); 1592a026809cSRussell King (Oracle) } 1593a026809cSRussell King (Oracle) 1594a026809cSRussell King (Oracle) if (port <= 4) { 1595a026809cSRussell King (Oracle) /* Internal PHYs */ 1596a026809cSRussell King (Oracle) __set_bit(PHY_INTERFACE_MODE_INTERNAL, interfaces); 1597a026809cSRussell King (Oracle) /* phylib default */ 1598a026809cSRussell King (Oracle) __set_bit(PHY_INTERFACE_MODE_GMII, interfaces); 1599a026809cSRussell King (Oracle) } 1600a026809cSRussell King (Oracle) 1601a026809cSRussell King (Oracle) config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000; 1602a026809cSRussell King (Oracle) } 1603a026809cSRussell King (Oracle) 16046b783dedSPawel Dembicki static int 16056b783dedSPawel Dembicki vsc73xx_port_vlan_filtering(struct dsa_switch *ds, int port, 16066b783dedSPawel Dembicki bool vlan_filtering, struct netlink_ext_ack *extack) 16076b783dedSPawel Dembicki { 16086b783dedSPawel Dembicki struct vsc73xx *vsc = ds->priv; 16096b783dedSPawel Dembicki 16106b783dedSPawel Dembicki /* The commit to hardware processed below is required because vsc73xx 16116b783dedSPawel Dembicki * is using tag_8021q. When vlan_filtering is disabled, tag_8021q uses 16126b783dedSPawel Dembicki * pvid/untagged vlans for port recognition. The values configured for 16136b783dedSPawel Dembicki * vlans and pvid/untagged states are stored in portinfo structure. 16146b783dedSPawel Dembicki * When vlan_filtering is enabled, we need to restore pvid/untagged from 16156b783dedSPawel Dembicki * portinfo structure. Analogous routine is processed when 16166b783dedSPawel Dembicki * vlan_filtering is disabled, but values used for tag_8021q are 16176b783dedSPawel Dembicki * restored. 16186b783dedSPawel Dembicki */ 16196b783dedSPawel Dembicki 16206b783dedSPawel Dembicki return vsc73xx_vlan_commit_settings(vsc, port); 16216b783dedSPawel Dembicki } 16226b783dedSPawel Dembicki 16236b783dedSPawel Dembicki static int vsc73xx_port_vlan_add(struct dsa_switch *ds, int port, 16246b783dedSPawel Dembicki const struct switchdev_obj_port_vlan *vlan, 16256b783dedSPawel Dembicki struct netlink_ext_ack *extack) 16266b783dedSPawel Dembicki { 16276b783dedSPawel Dembicki bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; 16286b783dedSPawel Dembicki bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; 16296b783dedSPawel Dembicki struct dsa_port *dp = dsa_to_port(ds, port); 16306b783dedSPawel Dembicki struct vsc73xx_bridge_vlan *vsc73xx_vlan; 16316b783dedSPawel Dembicki struct vsc73xx_vlan_summary summary; 16326b783dedSPawel Dembicki struct vsc73xx_portinfo *portinfo; 16336b783dedSPawel Dembicki struct vsc73xx *vsc = ds->priv; 16346b783dedSPawel Dembicki bool commit_to_hardware; 16356b783dedSPawel Dembicki int ret = 0; 16366b783dedSPawel Dembicki 16376b783dedSPawel Dembicki /* Be sure to deny alterations to the configuration done by tag_8021q. 16386b783dedSPawel Dembicki */ 16396b783dedSPawel Dembicki if (vid_is_dsa_8021q(vlan->vid)) { 16406b783dedSPawel Dembicki NL_SET_ERR_MSG_MOD(extack, 16416b783dedSPawel Dembicki "Range 3072-4095 reserved for dsa_8021q operation"); 16426b783dedSPawel Dembicki return -EBUSY; 16436b783dedSPawel Dembicki } 16446b783dedSPawel Dembicki 16456b783dedSPawel Dembicki /* The processed vlan->vid is excluded from the search because the VLAN 16466b783dedSPawel Dembicki * can be re-added with a different set of flags, so it's easiest to 16476b783dedSPawel Dembicki * ignore its old flags from the VLAN database software copy. 16486b783dedSPawel Dembicki */ 16496b783dedSPawel Dembicki vsc73xx_bridge_vlan_summary(vsc, port, &summary, vlan->vid); 16506b783dedSPawel Dembicki 16516b783dedSPawel Dembicki /* VSC73XX allows only three untagged states: none, one or all */ 16526b783dedSPawel Dembicki if ((untagged && summary.num_tagged > 0 && summary.num_untagged > 0) || 16536b783dedSPawel Dembicki (!untagged && summary.num_untagged > 1)) { 16546b783dedSPawel Dembicki NL_SET_ERR_MSG_MOD(extack, 16556b783dedSPawel Dembicki "Port can have only none, one or all untagged vlan"); 16566b783dedSPawel Dembicki return -EBUSY; 16576b783dedSPawel Dembicki } 16586b783dedSPawel Dembicki 16596b783dedSPawel Dembicki vsc73xx_vlan = vsc73xx_bridge_vlan_find(vsc, vlan->vid); 16606b783dedSPawel Dembicki 16616b783dedSPawel Dembicki if (!vsc73xx_vlan) { 16626b783dedSPawel Dembicki vsc73xx_vlan = kzalloc(sizeof(*vsc73xx_vlan), GFP_KERNEL); 16636b783dedSPawel Dembicki if (!vsc73xx_vlan) 16646b783dedSPawel Dembicki return -ENOMEM; 16656b783dedSPawel Dembicki 16666b783dedSPawel Dembicki vsc73xx_vlan->vid = vlan->vid; 16676b783dedSPawel Dembicki 16686b783dedSPawel Dembicki list_add_tail(&vsc73xx_vlan->list, &vsc->vlans); 16696b783dedSPawel Dembicki } 16706b783dedSPawel Dembicki 16716b783dedSPawel Dembicki vsc73xx_vlan->portmask |= BIT(port); 16726b783dedSPawel Dembicki 16736b783dedSPawel Dembicki /* CPU port must be always tagged because source port identification is 16746b783dedSPawel Dembicki * based on tag_8021q. 16756b783dedSPawel Dembicki */ 16766b783dedSPawel Dembicki if (port == CPU_PORT) 16776b783dedSPawel Dembicki goto update_vlan_table; 16786b783dedSPawel Dembicki 16796b783dedSPawel Dembicki if (untagged) 16806b783dedSPawel Dembicki vsc73xx_vlan->untagged |= BIT(port); 16816b783dedSPawel Dembicki else 16826b783dedSPawel Dembicki vsc73xx_vlan->untagged &= ~BIT(port); 16836b783dedSPawel Dembicki 16846b783dedSPawel Dembicki portinfo = &vsc->portinfo[port]; 16856b783dedSPawel Dembicki 16866b783dedSPawel Dembicki if (pvid) { 16876b783dedSPawel Dembicki portinfo->pvid_vlan_filtering_configured = true; 16886b783dedSPawel Dembicki portinfo->pvid_vlan_filtering = vlan->vid; 16896b783dedSPawel Dembicki } else if (portinfo->pvid_vlan_filtering_configured && 16906b783dedSPawel Dembicki portinfo->pvid_vlan_filtering == vlan->vid) { 16916b783dedSPawel Dembicki portinfo->pvid_vlan_filtering_configured = false; 16926b783dedSPawel Dembicki } 16936b783dedSPawel Dembicki 16946b783dedSPawel Dembicki commit_to_hardware = !vsc73xx_tag_8021q_active(dp); 16956b783dedSPawel Dembicki if (commit_to_hardware) { 16966b783dedSPawel Dembicki ret = vsc73xx_vlan_commit_settings(vsc, port); 16976b783dedSPawel Dembicki if (ret) 16986b783dedSPawel Dembicki goto err; 16996b783dedSPawel Dembicki } 17006b783dedSPawel Dembicki 17016b783dedSPawel Dembicki update_vlan_table: 17026b783dedSPawel Dembicki ret = vsc73xx_update_vlan_table(vsc, port, vlan->vid, true); 17036b783dedSPawel Dembicki if (!ret) 17046b783dedSPawel Dembicki return 0; 17056b783dedSPawel Dembicki err: 17066b783dedSPawel Dembicki vsc73xx_bridge_vlan_remove_port(vsc73xx_vlan, port); 17076b783dedSPawel Dembicki return ret; 17086b783dedSPawel Dembicki } 17096b783dedSPawel Dembicki 17106b783dedSPawel Dembicki static int vsc73xx_port_vlan_del(struct dsa_switch *ds, int port, 17116b783dedSPawel Dembicki const struct switchdev_obj_port_vlan *vlan) 17126b783dedSPawel Dembicki { 17136b783dedSPawel Dembicki struct vsc73xx_bridge_vlan *vsc73xx_vlan; 17146b783dedSPawel Dembicki struct vsc73xx_portinfo *portinfo; 17156b783dedSPawel Dembicki struct vsc73xx *vsc = ds->priv; 17166b783dedSPawel Dembicki bool commit_to_hardware; 17176b783dedSPawel Dembicki int ret; 17186b783dedSPawel Dembicki 17196b783dedSPawel Dembicki ret = vsc73xx_update_vlan_table(vsc, port, vlan->vid, false); 17206b783dedSPawel Dembicki if (ret) 17216b783dedSPawel Dembicki return ret; 17226b783dedSPawel Dembicki 17236b783dedSPawel Dembicki portinfo = &vsc->portinfo[port]; 17246b783dedSPawel Dembicki 17256b783dedSPawel Dembicki if (portinfo->pvid_vlan_filtering_configured && 17266b783dedSPawel Dembicki portinfo->pvid_vlan_filtering == vlan->vid) 17276b783dedSPawel Dembicki portinfo->pvid_vlan_filtering_configured = false; 17286b783dedSPawel Dembicki 17296b783dedSPawel Dembicki vsc73xx_vlan = vsc73xx_bridge_vlan_find(vsc, vlan->vid); 17306b783dedSPawel Dembicki 17316b783dedSPawel Dembicki if (vsc73xx_vlan) 17326b783dedSPawel Dembicki vsc73xx_bridge_vlan_remove_port(vsc73xx_vlan, port); 17336b783dedSPawel Dembicki 17346b783dedSPawel Dembicki commit_to_hardware = !vsc73xx_tag_8021q_active(dsa_to_port(ds, port)); 1735e3386ec4SPawel Dembicki 17366b783dedSPawel Dembicki if (commit_to_hardware) 17376b783dedSPawel Dembicki return vsc73xx_vlan_commit_settings(vsc, port); 17386b783dedSPawel Dembicki 17396b783dedSPawel Dembicki return 0; 17406b783dedSPawel Dembicki } 17416b783dedSPawel Dembicki 1742e3386ec4SPawel Dembicki static int vsc73xx_tag_8021q_vlan_add(struct dsa_switch *ds, int port, u16 vid, 1743e3386ec4SPawel Dembicki u16 flags) 1744e3386ec4SPawel Dembicki { 1745e3386ec4SPawel Dembicki bool pvid = flags & BRIDGE_VLAN_INFO_PVID; 1746e3386ec4SPawel Dembicki struct vsc73xx_portinfo *portinfo; 1747e3386ec4SPawel Dembicki struct vsc73xx *vsc = ds->priv; 1748e3386ec4SPawel Dembicki bool commit_to_hardware; 1749e3386ec4SPawel Dembicki int ret; 1750e3386ec4SPawel Dembicki 1751e3386ec4SPawel Dembicki portinfo = &vsc->portinfo[port]; 1752e3386ec4SPawel Dembicki 1753e3386ec4SPawel Dembicki if (pvid) { 1754e3386ec4SPawel Dembicki portinfo->pvid_tag_8021q_configured = true; 1755e3386ec4SPawel Dembicki portinfo->pvid_tag_8021q = vid; 1756e3386ec4SPawel Dembicki } 1757e3386ec4SPawel Dembicki 1758e3386ec4SPawel Dembicki commit_to_hardware = vsc73xx_tag_8021q_active(dsa_to_port(ds, port)); 1759e3386ec4SPawel Dembicki if (commit_to_hardware) { 1760e3386ec4SPawel Dembicki ret = vsc73xx_vlan_commit_settings(vsc, port); 1761e3386ec4SPawel Dembicki if (ret) 1762e3386ec4SPawel Dembicki return ret; 1763e3386ec4SPawel Dembicki } 1764e3386ec4SPawel Dembicki 1765e3386ec4SPawel Dembicki return vsc73xx_update_vlan_table(vsc, port, vid, true); 1766e3386ec4SPawel Dembicki } 1767e3386ec4SPawel Dembicki 1768e3386ec4SPawel Dembicki static int vsc73xx_tag_8021q_vlan_del(struct dsa_switch *ds, int port, u16 vid) 1769e3386ec4SPawel Dembicki { 1770e3386ec4SPawel Dembicki struct vsc73xx_portinfo *portinfo; 1771e3386ec4SPawel Dembicki struct vsc73xx *vsc = ds->priv; 1772e3386ec4SPawel Dembicki 1773e3386ec4SPawel Dembicki portinfo = &vsc->portinfo[port]; 1774e3386ec4SPawel Dembicki 1775e3386ec4SPawel Dembicki if (portinfo->pvid_tag_8021q_configured && 1776e3386ec4SPawel Dembicki portinfo->pvid_tag_8021q == vid) { 1777e3386ec4SPawel Dembicki struct dsa_port *dp = dsa_to_port(ds, port); 1778e3386ec4SPawel Dembicki bool commit_to_hardware; 1779e3386ec4SPawel Dembicki int err; 1780e3386ec4SPawel Dembicki 1781e3386ec4SPawel Dembicki portinfo->pvid_tag_8021q_configured = false; 1782e3386ec4SPawel Dembicki 1783e3386ec4SPawel Dembicki commit_to_hardware = vsc73xx_tag_8021q_active(dp); 1784e3386ec4SPawel Dembicki if (commit_to_hardware) { 1785e3386ec4SPawel Dembicki err = vsc73xx_vlan_commit_settings(vsc, port); 1786e3386ec4SPawel Dembicki if (err) 1787e3386ec4SPawel Dembicki return err; 1788e3386ec4SPawel Dembicki } 1789e3386ec4SPawel Dembicki } 1790e3386ec4SPawel Dembicki 1791e3386ec4SPawel Dembicki return vsc73xx_update_vlan_table(vsc, port, vid, false); 1792e3386ec4SPawel Dembicki } 1793e3386ec4SPawel Dembicki 1794259a7061SPawel Dembicki static int vsc73xx_port_pre_bridge_flags(struct dsa_switch *ds, int port, 1795259a7061SPawel Dembicki struct switchdev_brport_flags flags, 1796259a7061SPawel Dembicki struct netlink_ext_ack *extack) 1797259a7061SPawel Dembicki { 1798259a7061SPawel Dembicki if (flags.mask & ~BR_LEARNING) 1799259a7061SPawel Dembicki return -EINVAL; 1800259a7061SPawel Dembicki 1801259a7061SPawel Dembicki return 0; 1802259a7061SPawel Dembicki } 1803259a7061SPawel Dembicki 1804259a7061SPawel Dembicki static int vsc73xx_port_bridge_flags(struct dsa_switch *ds, int port, 1805259a7061SPawel Dembicki struct switchdev_brport_flags flags, 1806259a7061SPawel Dembicki struct netlink_ext_ack *extack) 1807259a7061SPawel Dembicki { 1808259a7061SPawel Dembicki if (flags.mask & BR_LEARNING) { 1809259a7061SPawel Dembicki u32 val = flags.val & BR_LEARNING ? BIT(port) : 0; 1810259a7061SPawel Dembicki struct vsc73xx *vsc = ds->priv; 1811259a7061SPawel Dembicki 1812259a7061SPawel Dembicki return vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, 1813259a7061SPawel Dembicki VSC73XX_LEARNMASK, BIT(port), val); 1814259a7061SPawel Dembicki } 1815259a7061SPawel Dembicki 1816259a7061SPawel Dembicki return 0; 1817259a7061SPawel Dembicki } 1818259a7061SPawel Dembicki 18191e5b23e5SPawel Dembicki static void vsc73xx_refresh_fwd_map(struct dsa_switch *ds, int port, u8 state) 18201e5b23e5SPawel Dembicki { 18211e5b23e5SPawel Dembicki struct dsa_port *other_dp, *dp = dsa_to_port(ds, port); 18221e5b23e5SPawel Dembicki struct vsc73xx *vsc = ds->priv; 18231e5b23e5SPawel Dembicki u16 mask; 18241e5b23e5SPawel Dembicki 18251e5b23e5SPawel Dembicki if (state != BR_STATE_FORWARDING) { 18261e5b23e5SPawel Dembicki /* Ports that aren't in the forwarding state must not 18271e5b23e5SPawel Dembicki * forward packets anywhere. 18281e5b23e5SPawel Dembicki */ 18291e5b23e5SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, 18301e5b23e5SPawel Dembicki VSC73XX_SRCMASKS + port, 18311e5b23e5SPawel Dembicki VSC73XX_SRCMASKS_PORTS_MASK, 0); 18321e5b23e5SPawel Dembicki 18331e5b23e5SPawel Dembicki dsa_switch_for_each_available_port(other_dp, ds) { 18341e5b23e5SPawel Dembicki if (other_dp == dp) 18351e5b23e5SPawel Dembicki continue; 18361e5b23e5SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, 18371e5b23e5SPawel Dembicki VSC73XX_SRCMASKS + other_dp->index, 18381e5b23e5SPawel Dembicki BIT(port), 0); 18391e5b23e5SPawel Dembicki } 18401e5b23e5SPawel Dembicki 18411e5b23e5SPawel Dembicki return; 18421e5b23e5SPawel Dembicki } 18431e5b23e5SPawel Dembicki 18441e5b23e5SPawel Dembicki /* Forwarding ports must forward to the CPU and to other ports 18451e5b23e5SPawel Dembicki * in the same bridge 18461e5b23e5SPawel Dembicki */ 18471e5b23e5SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, 18481e5b23e5SPawel Dembicki VSC73XX_SRCMASKS + CPU_PORT, BIT(port), BIT(port)); 18491e5b23e5SPawel Dembicki 18501e5b23e5SPawel Dembicki mask = BIT(CPU_PORT); 18511e5b23e5SPawel Dembicki 18521e5b23e5SPawel Dembicki dsa_switch_for_each_user_port(other_dp, ds) { 18531e5b23e5SPawel Dembicki int other_port = other_dp->index; 18541e5b23e5SPawel Dembicki 18551e5b23e5SPawel Dembicki if (port == other_port || !dsa_port_bridge_same(dp, other_dp) || 18561e5b23e5SPawel Dembicki other_dp->stp_state != BR_STATE_FORWARDING) 18571e5b23e5SPawel Dembicki continue; 18581e5b23e5SPawel Dembicki 18591e5b23e5SPawel Dembicki mask |= BIT(other_port); 18601e5b23e5SPawel Dembicki 18611e5b23e5SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, 18621e5b23e5SPawel Dembicki VSC73XX_SRCMASKS + other_port, 18631e5b23e5SPawel Dembicki BIT(port), BIT(port)); 18641e5b23e5SPawel Dembicki } 18651e5b23e5SPawel Dembicki 18661e5b23e5SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, 18671e5b23e5SPawel Dembicki VSC73XX_SRCMASKS + port, 18681e5b23e5SPawel Dembicki VSC73XX_SRCMASKS_PORTS_MASK, mask); 18691e5b23e5SPawel Dembicki } 18701e5b23e5SPawel Dembicki 18711e5b23e5SPawel Dembicki /* FIXME: STP frames aren't forwarded at this moment. BPDU frames are 18721e5b23e5SPawel Dembicki * forwarded only from and to PI/SI interface. For more info see chapter 18731e5b23e5SPawel Dembicki * 2.7.1 (CPU Forwarding) in datasheet. 18741e5b23e5SPawel Dembicki * This function is required for tag_8021q operations. 18751e5b23e5SPawel Dembicki */ 18761e5b23e5SPawel Dembicki static void vsc73xx_port_stp_state_set(struct dsa_switch *ds, int port, 18771e5b23e5SPawel Dembicki u8 state) 18781e5b23e5SPawel Dembicki { 1879259a7061SPawel Dembicki struct dsa_port *dp = dsa_to_port(ds, port); 18801e5b23e5SPawel Dembicki struct vsc73xx *vsc = ds->priv; 1881259a7061SPawel Dembicki u32 val = 0; 1882259a7061SPawel Dembicki 1883259a7061SPawel Dembicki if (state == BR_STATE_LEARNING || state == BR_STATE_FORWARDING) 1884259a7061SPawel Dembicki val = dp->learning ? BIT(port) : 0; 1885259a7061SPawel Dembicki 1886259a7061SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, 1887259a7061SPawel Dembicki VSC73XX_LEARNMASK, BIT(port), val); 18881e5b23e5SPawel Dembicki 18891e5b23e5SPawel Dembicki val = (state == BR_STATE_BLOCKING || state == BR_STATE_DISABLED) ? 18901e5b23e5SPawel Dembicki 0 : BIT(port); 18911e5b23e5SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, 18921e5b23e5SPawel Dembicki VSC73XX_RECVMASK, BIT(port), val); 18931e5b23e5SPawel Dembicki 18941e5b23e5SPawel Dembicki /* CPU Port should always forward packets when user ports are forwarding 18951e5b23e5SPawel Dembicki * so let's configure it from other ports only. 18961e5b23e5SPawel Dembicki */ 18971e5b23e5SPawel Dembicki if (port != CPU_PORT) 18981e5b23e5SPawel Dembicki vsc73xx_refresh_fwd_map(ds, port, state); 18991e5b23e5SPawel Dembicki } 19001e5b23e5SPawel Dembicki 1901*075e3d30SPawel Dembicki static u16 vsc73xx_calc_hash(const unsigned char *addr, u16 vid) 1902*075e3d30SPawel Dembicki { 1903*075e3d30SPawel Dembicki /* VID 5-0, MAC 47-44 */ 1904*075e3d30SPawel Dembicki u16 hash = FIELD_PREP(VSC73XX_HASH0_VID_TO_MASK, 1905*075e3d30SPawel Dembicki FIELD_GET(VSC73XX_HASH0_VID_FROM_MASK, vid)) | 1906*075e3d30SPawel Dembicki FIELD_PREP(VSC73XX_HASH0_MAC0_TO_MASK, 1907*075e3d30SPawel Dembicki FIELD_GET(VSC73XX_HASH0_MAC0_FROM_MASK, addr[0])); 1908*075e3d30SPawel Dembicki /* MAC 43-33 */ 1909*075e3d30SPawel Dembicki hash ^= FIELD_PREP(VSC73XX_HASH1_MAC0_TO_MASK, 1910*075e3d30SPawel Dembicki FIELD_GET(VSC73XX_HASH1_MAC0_FROM_MASK, addr[0])) | 1911*075e3d30SPawel Dembicki FIELD_PREP(VSC73XX_HASH1_MAC1_TO_MASK, 1912*075e3d30SPawel Dembicki FIELD_GET(VSC73XX_HASH1_MAC1_FROM_MASK, addr[1])); 1913*075e3d30SPawel Dembicki /* MAC 32-22 */ 1914*075e3d30SPawel Dembicki hash ^= FIELD_PREP(VSC73XX_HASH2_MAC1_TO_MASK, 1915*075e3d30SPawel Dembicki FIELD_GET(VSC73XX_HASH2_MAC1_FROM_MASK, addr[1])) | 1916*075e3d30SPawel Dembicki FIELD_PREP(VSC73XX_HASH2_MAC2_TO_MASK, 1917*075e3d30SPawel Dembicki FIELD_GET(VSC73XX_HASH2_MAC2_FROM_MASK, addr[2])) | 1918*075e3d30SPawel Dembicki FIELD_PREP(VSC73XX_HASH2_MAC3_TO_MASK, 1919*075e3d30SPawel Dembicki FIELD_GET(VSC73XX_HASH2_MAC3_FROM_MASK, addr[3])); 1920*075e3d30SPawel Dembicki /* MAC 21-11 */ 1921*075e3d30SPawel Dembicki hash ^= FIELD_PREP(VSC73XX_HASH3_MAC3_TO_MASK, 1922*075e3d30SPawel Dembicki FIELD_GET(VSC73XX_HASH3_MAC3_FROM_MASK, addr[3])) | 1923*075e3d30SPawel Dembicki FIELD_PREP(VSC73XX_HASH3_MAC4_TO_MASK, 1924*075e3d30SPawel Dembicki FIELD_GET(VSC73XX_HASH3_MAC4_FROM_MASK, addr[4])); 1925*075e3d30SPawel Dembicki /* MAC 10-0 */ 1926*075e3d30SPawel Dembicki hash ^= FIELD_PREP(VSC73XX_HASH4_MAC4_TO_MASK, 1927*075e3d30SPawel Dembicki FIELD_GET(VSC73XX_HASH4_MAC4_FROM_MASK, addr[4])) | 1928*075e3d30SPawel Dembicki addr[5]; 1929*075e3d30SPawel Dembicki 1930*075e3d30SPawel Dembicki return hash; 1931*075e3d30SPawel Dembicki } 1932*075e3d30SPawel Dembicki 1933*075e3d30SPawel Dembicki static int 1934*075e3d30SPawel Dembicki vsc73xx_port_wait_for_mac_table_cmd(struct vsc73xx *vsc) 1935*075e3d30SPawel Dembicki { 1936*075e3d30SPawel Dembicki int ret, err; 1937*075e3d30SPawel Dembicki u32 val; 1938*075e3d30SPawel Dembicki 1939*075e3d30SPawel Dembicki ret = read_poll_timeout(vsc73xx_read, err, 1940*075e3d30SPawel Dembicki err < 0 || 1941*075e3d30SPawel Dembicki ((val & VSC73XX_MACACCESS_CMD_MASK) == 1942*075e3d30SPawel Dembicki VSC73XX_MACACCESS_CMD_IDLE), 1943*075e3d30SPawel Dembicki VSC73XX_POLL_SLEEP_US, VSC73XX_POLL_TIMEOUT_US, 1944*075e3d30SPawel Dembicki false, vsc, VSC73XX_BLOCK_ANALYZER, 1945*075e3d30SPawel Dembicki 0, VSC73XX_MACACCESS, &val); 1946*075e3d30SPawel Dembicki if (ret) 1947*075e3d30SPawel Dembicki return ret; 1948*075e3d30SPawel Dembicki return err; 1949*075e3d30SPawel Dembicki } 1950*075e3d30SPawel Dembicki 1951*075e3d30SPawel Dembicki static int vsc73xx_port_read_mac_table_row(struct vsc73xx *vsc, u16 index, 1952*075e3d30SPawel Dembicki struct vsc73xx_fdb *fdb) 1953*075e3d30SPawel Dembicki { 1954*075e3d30SPawel Dembicki int ret, i; 1955*075e3d30SPawel Dembicki u32 val; 1956*075e3d30SPawel Dembicki 1957*075e3d30SPawel Dembicki if (!fdb) 1958*075e3d30SPawel Dembicki return -EINVAL; 1959*075e3d30SPawel Dembicki if (index >= VSC73XX_NUM_FDB_ROWS) 1960*075e3d30SPawel Dembicki return -EINVAL; 1961*075e3d30SPawel Dembicki 1962*075e3d30SPawel Dembicki for (i = 0; i < VSC73XX_NUM_BUCKETS; i++) { 1963*075e3d30SPawel Dembicki ret = vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, 1964*075e3d30SPawel Dembicki VSC73XX_MACTINDX, 1965*075e3d30SPawel Dembicki (i ? 0 : VSC73XX_MACTINDX_SHADOW) | 1966*075e3d30SPawel Dembicki FIELD_PREP(VSC73XX_MACTINDX_BUCKET_MSK, i) | 1967*075e3d30SPawel Dembicki index); 1968*075e3d30SPawel Dembicki if (ret) 1969*075e3d30SPawel Dembicki return ret; 1970*075e3d30SPawel Dembicki 1971*075e3d30SPawel Dembicki ret = vsc73xx_port_wait_for_mac_table_cmd(vsc); 1972*075e3d30SPawel Dembicki if (ret) 1973*075e3d30SPawel Dembicki return ret; 1974*075e3d30SPawel Dembicki 1975*075e3d30SPawel Dembicki ret = vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, 1976*075e3d30SPawel Dembicki VSC73XX_MACACCESS, 1977*075e3d30SPawel Dembicki VSC73XX_MACACCESS_CMD_MASK, 1978*075e3d30SPawel Dembicki VSC73XX_MACACCESS_CMD_READ_ENTRY); 1979*075e3d30SPawel Dembicki if (ret) 1980*075e3d30SPawel Dembicki return ret; 1981*075e3d30SPawel Dembicki 1982*075e3d30SPawel Dembicki ret = vsc73xx_port_wait_for_mac_table_cmd(vsc); 1983*075e3d30SPawel Dembicki if (ret) 1984*075e3d30SPawel Dembicki return ret; 1985*075e3d30SPawel Dembicki 1986*075e3d30SPawel Dembicki ret = vsc73xx_read(vsc, VSC73XX_BLOCK_ANALYZER, 0, 1987*075e3d30SPawel Dembicki VSC73XX_MACACCESS, &val); 1988*075e3d30SPawel Dembicki if (ret) 1989*075e3d30SPawel Dembicki return ret; 1990*075e3d30SPawel Dembicki 1991*075e3d30SPawel Dembicki fdb[i].valid = FIELD_GET(VSC73XX_MACACCESS_VALID, val); 1992*075e3d30SPawel Dembicki if (!fdb[i].valid) 1993*075e3d30SPawel Dembicki continue; 1994*075e3d30SPawel Dembicki 1995*075e3d30SPawel Dembicki fdb[i].port = FIELD_GET(VSC73XX_MACACCESS_DEST_IDX_MASK, val); 1996*075e3d30SPawel Dembicki 1997*075e3d30SPawel Dembicki ret = vsc73xx_read(vsc, VSC73XX_BLOCK_ANALYZER, 0, 1998*075e3d30SPawel Dembicki VSC73XX_MACHDATA, &val); 1999*075e3d30SPawel Dembicki if (ret) 2000*075e3d30SPawel Dembicki return ret; 2001*075e3d30SPawel Dembicki 2002*075e3d30SPawel Dembicki fdb[i].vid = FIELD_GET(VSC73XX_MACHDATA_VID, val); 2003*075e3d30SPawel Dembicki fdb[i].mac[0] = FIELD_GET(VSC73XX_MACHDATA_MAC0, val); 2004*075e3d30SPawel Dembicki fdb[i].mac[1] = FIELD_GET(VSC73XX_MACHDATA_MAC1, val); 2005*075e3d30SPawel Dembicki 2006*075e3d30SPawel Dembicki ret = vsc73xx_read(vsc, VSC73XX_BLOCK_ANALYZER, 0, 2007*075e3d30SPawel Dembicki VSC73XX_MACLDATA, &val); 2008*075e3d30SPawel Dembicki if (ret) 2009*075e3d30SPawel Dembicki return ret; 2010*075e3d30SPawel Dembicki 2011*075e3d30SPawel Dembicki fdb[i].mac[2] = FIELD_GET(VSC73XX_MACLDATA_MAC2, val); 2012*075e3d30SPawel Dembicki fdb[i].mac[3] = FIELD_GET(VSC73XX_MACLDATA_MAC3, val); 2013*075e3d30SPawel Dembicki fdb[i].mac[4] = FIELD_GET(VSC73XX_MACLDATA_MAC4, val); 2014*075e3d30SPawel Dembicki fdb[i].mac[5] = FIELD_GET(VSC73XX_MACLDATA_MAC5, val); 2015*075e3d30SPawel Dembicki } 2016*075e3d30SPawel Dembicki 2017*075e3d30SPawel Dembicki return ret; 2018*075e3d30SPawel Dembicki } 2019*075e3d30SPawel Dembicki 2020*075e3d30SPawel Dembicki static int 2021*075e3d30SPawel Dembicki vsc73xx_fdb_operation(struct vsc73xx *vsc, const unsigned char *addr, u16 vid, 2022*075e3d30SPawel Dembicki u16 hash, u16 cmd_mask, u16 cmd_val) 2023*075e3d30SPawel Dembicki { 2024*075e3d30SPawel Dembicki int ret; 2025*075e3d30SPawel Dembicki u32 val; 2026*075e3d30SPawel Dembicki 2027*075e3d30SPawel Dembicki val = FIELD_PREP(VSC73XX_MACHDATA_VID, vid) | 2028*075e3d30SPawel Dembicki FIELD_PREP(VSC73XX_MACHDATA_MAC0, addr[0]) | 2029*075e3d30SPawel Dembicki FIELD_PREP(VSC73XX_MACHDATA_MAC1, addr[1]); 2030*075e3d30SPawel Dembicki ret = vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_MACHDATA, 2031*075e3d30SPawel Dembicki val); 2032*075e3d30SPawel Dembicki if (ret) 2033*075e3d30SPawel Dembicki return ret; 2034*075e3d30SPawel Dembicki 2035*075e3d30SPawel Dembicki val = FIELD_PREP(VSC73XX_MACLDATA_MAC2, addr[2]) | 2036*075e3d30SPawel Dembicki FIELD_PREP(VSC73XX_MACLDATA_MAC3, addr[3]) | 2037*075e3d30SPawel Dembicki FIELD_PREP(VSC73XX_MACLDATA_MAC4, addr[4]) | 2038*075e3d30SPawel Dembicki FIELD_PREP(VSC73XX_MACLDATA_MAC5, addr[5]); 2039*075e3d30SPawel Dembicki ret = vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_MACLDATA, 2040*075e3d30SPawel Dembicki val); 2041*075e3d30SPawel Dembicki if (ret) 2042*075e3d30SPawel Dembicki return ret; 2043*075e3d30SPawel Dembicki 2044*075e3d30SPawel Dembicki ret = vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_MACTINDX, 2045*075e3d30SPawel Dembicki hash); 2046*075e3d30SPawel Dembicki if (ret) 2047*075e3d30SPawel Dembicki return ret; 2048*075e3d30SPawel Dembicki 2049*075e3d30SPawel Dembicki ret = vsc73xx_port_wait_for_mac_table_cmd(vsc); 2050*075e3d30SPawel Dembicki if (ret) 2051*075e3d30SPawel Dembicki return ret; 2052*075e3d30SPawel Dembicki 2053*075e3d30SPawel Dembicki ret = vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, 2054*075e3d30SPawel Dembicki VSC73XX_MACACCESS, cmd_mask, cmd_val); 2055*075e3d30SPawel Dembicki if (ret) 2056*075e3d30SPawel Dembicki return ret; 2057*075e3d30SPawel Dembicki 2058*075e3d30SPawel Dembicki return vsc73xx_port_wait_for_mac_table_cmd(vsc); 2059*075e3d30SPawel Dembicki } 2060*075e3d30SPawel Dembicki 2061*075e3d30SPawel Dembicki static int vsc73xx_fdb_del_entry(struct vsc73xx *vsc, int port, 2062*075e3d30SPawel Dembicki const unsigned char *addr, u16 vid) 2063*075e3d30SPawel Dembicki { 2064*075e3d30SPawel Dembicki struct vsc73xx_fdb fdb[VSC73XX_NUM_BUCKETS]; 2065*075e3d30SPawel Dembicki u16 hash = vsc73xx_calc_hash(addr, vid); 2066*075e3d30SPawel Dembicki int bucket, ret; 2067*075e3d30SPawel Dembicki 2068*075e3d30SPawel Dembicki mutex_lock(&vsc->fdb_lock); 2069*075e3d30SPawel Dembicki 2070*075e3d30SPawel Dembicki ret = vsc73xx_port_read_mac_table_row(vsc, hash, fdb); 2071*075e3d30SPawel Dembicki if (ret) 2072*075e3d30SPawel Dembicki goto err; 2073*075e3d30SPawel Dembicki 2074*075e3d30SPawel Dembicki for (bucket = 0; bucket < VSC73XX_NUM_BUCKETS; bucket++) { 2075*075e3d30SPawel Dembicki if (fdb[bucket].valid && fdb[bucket].port == port && 2076*075e3d30SPawel Dembicki ether_addr_equal(addr, fdb[bucket].mac)) 2077*075e3d30SPawel Dembicki break; 2078*075e3d30SPawel Dembicki } 2079*075e3d30SPawel Dembicki 2080*075e3d30SPawel Dembicki if (bucket == VSC73XX_NUM_BUCKETS) { 2081*075e3d30SPawel Dembicki /* Can't find MAC in MAC table */ 2082*075e3d30SPawel Dembicki ret = -ENODATA; 2083*075e3d30SPawel Dembicki goto err; 2084*075e3d30SPawel Dembicki } 2085*075e3d30SPawel Dembicki 2086*075e3d30SPawel Dembicki ret = vsc73xx_fdb_operation(vsc, addr, vid, hash, 2087*075e3d30SPawel Dembicki VSC73XX_MACACCESS_CMD_MASK, 2088*075e3d30SPawel Dembicki VSC73XX_MACACCESS_CMD_FORGET); 2089*075e3d30SPawel Dembicki err: 2090*075e3d30SPawel Dembicki mutex_unlock(&vsc->fdb_lock); 2091*075e3d30SPawel Dembicki return ret; 2092*075e3d30SPawel Dembicki } 2093*075e3d30SPawel Dembicki 2094*075e3d30SPawel Dembicki static int vsc73xx_fdb_add_entry(struct vsc73xx *vsc, int port, 2095*075e3d30SPawel Dembicki const unsigned char *addr, u16 vid) 2096*075e3d30SPawel Dembicki { 2097*075e3d30SPawel Dembicki struct vsc73xx_fdb fdb[VSC73XX_NUM_BUCKETS]; 2098*075e3d30SPawel Dembicki u16 hash = vsc73xx_calc_hash(addr, vid); 2099*075e3d30SPawel Dembicki int bucket, ret; 2100*075e3d30SPawel Dembicki u32 val; 2101*075e3d30SPawel Dembicki 2102*075e3d30SPawel Dembicki mutex_lock(&vsc->fdb_lock); 2103*075e3d30SPawel Dembicki 2104*075e3d30SPawel Dembicki ret = vsc73xx_port_read_mac_table_row(vsc, hash, fdb); 2105*075e3d30SPawel Dembicki if (ret) 2106*075e3d30SPawel Dembicki goto err; 2107*075e3d30SPawel Dembicki 2108*075e3d30SPawel Dembicki for (bucket = 0; bucket < VSC73XX_NUM_BUCKETS; bucket++) { 2109*075e3d30SPawel Dembicki if (!fdb[bucket].valid) 2110*075e3d30SPawel Dembicki break; 2111*075e3d30SPawel Dembicki } 2112*075e3d30SPawel Dembicki 2113*075e3d30SPawel Dembicki if (bucket == VSC73XX_NUM_BUCKETS) { 2114*075e3d30SPawel Dembicki /* Bucket is full */ 2115*075e3d30SPawel Dembicki ret = -EOVERFLOW; 2116*075e3d30SPawel Dembicki goto err; 2117*075e3d30SPawel Dembicki } 2118*075e3d30SPawel Dembicki 2119*075e3d30SPawel Dembicki val = VSC73XX_MACACCESS_VALID | VSC73XX_MACACCESS_LOCKED | 2120*075e3d30SPawel Dembicki FIELD_PREP(VSC73XX_MACACCESS_DEST_IDX_MASK, port) | 2121*075e3d30SPawel Dembicki VSC73XX_MACACCESS_CMD_LEARN; 2122*075e3d30SPawel Dembicki ret = vsc73xx_fdb_operation(vsc, addr, vid, hash, 2123*075e3d30SPawel Dembicki VSC73XX_MACACCESS_VALID | 2124*075e3d30SPawel Dembicki VSC73XX_MACACCESS_LOCKED | 2125*075e3d30SPawel Dembicki VSC73XX_MACACCESS_DEST_IDX_MASK | 2126*075e3d30SPawel Dembicki VSC73XX_MACACCESS_CMD_MASK, val); 2127*075e3d30SPawel Dembicki err: 2128*075e3d30SPawel Dembicki mutex_unlock(&vsc->fdb_lock); 2129*075e3d30SPawel Dembicki return ret; 2130*075e3d30SPawel Dembicki } 2131*075e3d30SPawel Dembicki 2132*075e3d30SPawel Dembicki static int vsc73xx_fdb_add(struct dsa_switch *ds, int port, 2133*075e3d30SPawel Dembicki const unsigned char *addr, u16 vid, struct dsa_db db) 2134*075e3d30SPawel Dembicki { 2135*075e3d30SPawel Dembicki struct vsc73xx *vsc = ds->priv; 2136*075e3d30SPawel Dembicki 2137*075e3d30SPawel Dembicki if (!vid) { 2138*075e3d30SPawel Dembicki switch (db.type) { 2139*075e3d30SPawel Dembicki case DSA_DB_PORT: 2140*075e3d30SPawel Dembicki vid = dsa_tag_8021q_standalone_vid(db.dp); 2141*075e3d30SPawel Dembicki break; 2142*075e3d30SPawel Dembicki case DSA_DB_BRIDGE: 2143*075e3d30SPawel Dembicki vid = dsa_tag_8021q_bridge_vid(db.bridge.num); 2144*075e3d30SPawel Dembicki break; 2145*075e3d30SPawel Dembicki default: 2146*075e3d30SPawel Dembicki return -EOPNOTSUPP; 2147*075e3d30SPawel Dembicki } 2148*075e3d30SPawel Dembicki } 2149*075e3d30SPawel Dembicki 2150*075e3d30SPawel Dembicki return vsc73xx_fdb_add_entry(vsc, port, addr, vid); 2151*075e3d30SPawel Dembicki } 2152*075e3d30SPawel Dembicki 2153*075e3d30SPawel Dembicki static int vsc73xx_fdb_del(struct dsa_switch *ds, int port, 2154*075e3d30SPawel Dembicki const unsigned char *addr, u16 vid, struct dsa_db db) 2155*075e3d30SPawel Dembicki { 2156*075e3d30SPawel Dembicki struct vsc73xx *vsc = ds->priv; 2157*075e3d30SPawel Dembicki 2158*075e3d30SPawel Dembicki if (!vid) { 2159*075e3d30SPawel Dembicki switch (db.type) { 2160*075e3d30SPawel Dembicki case DSA_DB_PORT: 2161*075e3d30SPawel Dembicki vid = dsa_tag_8021q_standalone_vid(db.dp); 2162*075e3d30SPawel Dembicki break; 2163*075e3d30SPawel Dembicki case DSA_DB_BRIDGE: 2164*075e3d30SPawel Dembicki vid = dsa_tag_8021q_bridge_vid(db.bridge.num); 2165*075e3d30SPawel Dembicki break; 2166*075e3d30SPawel Dembicki default: 2167*075e3d30SPawel Dembicki return -EOPNOTSUPP; 2168*075e3d30SPawel Dembicki } 2169*075e3d30SPawel Dembicki } 2170*075e3d30SPawel Dembicki 2171*075e3d30SPawel Dembicki return vsc73xx_fdb_del_entry(vsc, port, addr, vid); 2172*075e3d30SPawel Dembicki } 2173*075e3d30SPawel Dembicki 2174*075e3d30SPawel Dembicki static int vsc73xx_port_fdb_dump(struct dsa_switch *ds, 2175*075e3d30SPawel Dembicki int port, dsa_fdb_dump_cb_t *cb, void *data) 2176*075e3d30SPawel Dembicki { 2177*075e3d30SPawel Dembicki struct vsc73xx_fdb fdb[VSC73XX_NUM_BUCKETS]; 2178*075e3d30SPawel Dembicki struct vsc73xx *vsc = ds->priv; 2179*075e3d30SPawel Dembicki u16 i, bucket; 2180*075e3d30SPawel Dembicki int err = 0; 2181*075e3d30SPawel Dembicki 2182*075e3d30SPawel Dembicki mutex_lock(&vsc->fdb_lock); 2183*075e3d30SPawel Dembicki 2184*075e3d30SPawel Dembicki for (i = 0; i < VSC73XX_NUM_FDB_ROWS; i++) { 2185*075e3d30SPawel Dembicki err = vsc73xx_port_read_mac_table_row(vsc, i, fdb); 2186*075e3d30SPawel Dembicki if (err) 2187*075e3d30SPawel Dembicki goto unlock; 2188*075e3d30SPawel Dembicki 2189*075e3d30SPawel Dembicki for (bucket = 0; bucket < VSC73XX_NUM_BUCKETS; bucket++) { 2190*075e3d30SPawel Dembicki if (!fdb[bucket].valid || fdb[bucket].port != port) 2191*075e3d30SPawel Dembicki continue; 2192*075e3d30SPawel Dembicki 2193*075e3d30SPawel Dembicki /* We need to hide dsa_8021q VLANs from the user */ 2194*075e3d30SPawel Dembicki if (vid_is_dsa_8021q(fdb[bucket].vid)) 2195*075e3d30SPawel Dembicki fdb[bucket].vid = 0; 2196*075e3d30SPawel Dembicki 2197*075e3d30SPawel Dembicki err = cb(fdb[bucket].mac, fdb[bucket].vid, false, data); 2198*075e3d30SPawel Dembicki if (err) 2199*075e3d30SPawel Dembicki goto unlock; 2200*075e3d30SPawel Dembicki } 2201*075e3d30SPawel Dembicki } 2202*075e3d30SPawel Dembicki unlock: 2203*075e3d30SPawel Dembicki mutex_unlock(&vsc->fdb_lock); 2204*075e3d30SPawel Dembicki return err; 2205*075e3d30SPawel Dembicki } 2206*075e3d30SPawel Dembicki 220721fc3416SPawel Dembicki static const struct phylink_mac_ops vsc73xx_phylink_mac_ops = { 220821fc3416SPawel Dembicki .mac_config = vsc73xx_mac_config, 220921fc3416SPawel Dembicki .mac_link_down = vsc73xx_mac_link_down, 221021fc3416SPawel Dembicki .mac_link_up = vsc73xx_mac_link_up, 221121fc3416SPawel Dembicki }; 221221fc3416SPawel Dembicki 221395711cd5SPawel Dembicki static const struct dsa_switch_ops vsc73xx_ds_ops = { 221495711cd5SPawel Dembicki .get_tag_protocol = vsc73xx_get_tag_protocol, 221595711cd5SPawel Dembicki .setup = vsc73xx_setup, 2216e3386ec4SPawel Dembicki .teardown = vsc73xx_teardown, 221795711cd5SPawel Dembicki .phy_read = vsc73xx_phy_read, 221895711cd5SPawel Dembicki .phy_write = vsc73xx_phy_write, 221995711cd5SPawel Dembicki .get_strings = vsc73xx_get_strings, 222095711cd5SPawel Dembicki .get_ethtool_stats = vsc73xx_get_ethtool_stats, 222195711cd5SPawel Dembicki .get_sset_count = vsc73xx_get_sset_count, 222295711cd5SPawel Dembicki .port_enable = vsc73xx_port_enable, 222395711cd5SPawel Dembicki .port_disable = vsc73xx_port_disable, 2224259a7061SPawel Dembicki .port_pre_bridge_flags = vsc73xx_port_pre_bridge_flags, 2225259a7061SPawel Dembicki .port_bridge_flags = vsc73xx_port_bridge_flags, 22266dfaaa27SPawel Dembicki .port_bridge_join = dsa_tag_8021q_bridge_join, 22276dfaaa27SPawel Dembicki .port_bridge_leave = dsa_tag_8021q_bridge_leave, 2228fb77ffc6SVladimir Oltean .port_change_mtu = vsc73xx_change_mtu, 2229*075e3d30SPawel Dembicki .port_fdb_add = vsc73xx_fdb_add, 2230*075e3d30SPawel Dembicki .port_fdb_del = vsc73xx_fdb_del, 2231*075e3d30SPawel Dembicki .port_fdb_dump = vsc73xx_port_fdb_dump, 2232fb77ffc6SVladimir Oltean .port_max_mtu = vsc73xx_get_max_mtu, 22331e5b23e5SPawel Dembicki .port_stp_state_set = vsc73xx_port_stp_state_set, 22346b783dedSPawel Dembicki .port_vlan_filtering = vsc73xx_port_vlan_filtering, 22356b783dedSPawel Dembicki .port_vlan_add = vsc73xx_port_vlan_add, 22366b783dedSPawel Dembicki .port_vlan_del = vsc73xx_port_vlan_del, 2237a026809cSRussell King (Oracle) .phylink_get_caps = vsc73xx_phylink_get_caps, 2238e3386ec4SPawel Dembicki .tag_8021q_vlan_add = vsc73xx_tag_8021q_vlan_add, 2239e3386ec4SPawel Dembicki .tag_8021q_vlan_del = vsc73xx_tag_8021q_vlan_del, 224095711cd5SPawel Dembicki }; 224195711cd5SPawel Dembicki 224295711cd5SPawel Dembicki static int vsc73xx_gpio_get(struct gpio_chip *chip, unsigned int offset) 224395711cd5SPawel Dembicki { 224495711cd5SPawel Dembicki struct vsc73xx *vsc = gpiochip_get_data(chip); 224595711cd5SPawel Dembicki u32 val; 224695711cd5SPawel Dembicki int ret; 224795711cd5SPawel Dembicki 224895711cd5SPawel Dembicki ret = vsc73xx_read(vsc, VSC73XX_BLOCK_SYSTEM, 0, 224995711cd5SPawel Dembicki VSC73XX_GPIO, &val); 225095711cd5SPawel Dembicki if (ret) 225195711cd5SPawel Dembicki return ret; 225295711cd5SPawel Dembicki 225395711cd5SPawel Dembicki return !!(val & BIT(offset)); 225495711cd5SPawel Dembicki } 225595711cd5SPawel Dembicki 225695711cd5SPawel Dembicki static void vsc73xx_gpio_set(struct gpio_chip *chip, unsigned int offset, 225795711cd5SPawel Dembicki int val) 225895711cd5SPawel Dembicki { 225995711cd5SPawel Dembicki struct vsc73xx *vsc = gpiochip_get_data(chip); 226095711cd5SPawel Dembicki u32 tmp = val ? BIT(offset) : 0; 226195711cd5SPawel Dembicki 226295711cd5SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_SYSTEM, 0, 226395711cd5SPawel Dembicki VSC73XX_GPIO, BIT(offset), tmp); 226495711cd5SPawel Dembicki } 226595711cd5SPawel Dembicki 226695711cd5SPawel Dembicki static int vsc73xx_gpio_direction_output(struct gpio_chip *chip, 226795711cd5SPawel Dembicki unsigned int offset, int val) 226895711cd5SPawel Dembicki { 226995711cd5SPawel Dembicki struct vsc73xx *vsc = gpiochip_get_data(chip); 227095711cd5SPawel Dembicki u32 tmp = val ? BIT(offset) : 0; 227195711cd5SPawel Dembicki 227295711cd5SPawel Dembicki return vsc73xx_update_bits(vsc, VSC73XX_BLOCK_SYSTEM, 0, 227395711cd5SPawel Dembicki VSC73XX_GPIO, BIT(offset + 4) | BIT(offset), 227495711cd5SPawel Dembicki BIT(offset + 4) | tmp); 227595711cd5SPawel Dembicki } 227695711cd5SPawel Dembicki 227795711cd5SPawel Dembicki static int vsc73xx_gpio_direction_input(struct gpio_chip *chip, 227895711cd5SPawel Dembicki unsigned int offset) 227995711cd5SPawel Dembicki { 228095711cd5SPawel Dembicki struct vsc73xx *vsc = gpiochip_get_data(chip); 228195711cd5SPawel Dembicki 228295711cd5SPawel Dembicki return vsc73xx_update_bits(vsc, VSC73XX_BLOCK_SYSTEM, 0, 228395711cd5SPawel Dembicki VSC73XX_GPIO, BIT(offset + 4), 228495711cd5SPawel Dembicki 0); 228595711cd5SPawel Dembicki } 228695711cd5SPawel Dembicki 228795711cd5SPawel Dembicki static int vsc73xx_gpio_get_direction(struct gpio_chip *chip, 228895711cd5SPawel Dembicki unsigned int offset) 228995711cd5SPawel Dembicki { 229095711cd5SPawel Dembicki struct vsc73xx *vsc = gpiochip_get_data(chip); 229195711cd5SPawel Dembicki u32 val; 229295711cd5SPawel Dembicki int ret; 229395711cd5SPawel Dembicki 229495711cd5SPawel Dembicki ret = vsc73xx_read(vsc, VSC73XX_BLOCK_SYSTEM, 0, 229595711cd5SPawel Dembicki VSC73XX_GPIO, &val); 229695711cd5SPawel Dembicki if (ret) 229795711cd5SPawel Dembicki return ret; 229895711cd5SPawel Dembicki 229995711cd5SPawel Dembicki return !(val & BIT(offset + 4)); 230095711cd5SPawel Dembicki } 230195711cd5SPawel Dembicki 230295711cd5SPawel Dembicki static int vsc73xx_gpio_probe(struct vsc73xx *vsc) 230395711cd5SPawel Dembicki { 230495711cd5SPawel Dembicki int ret; 230595711cd5SPawel Dembicki 230695711cd5SPawel Dembicki vsc->gc.label = devm_kasprintf(vsc->dev, GFP_KERNEL, "VSC%04x", 230795711cd5SPawel Dembicki vsc->chipid); 2308776dac5aSKunwu Chan if (!vsc->gc.label) 2309776dac5aSKunwu Chan return -ENOMEM; 231095711cd5SPawel Dembicki vsc->gc.ngpio = 4; 231195711cd5SPawel Dembicki vsc->gc.owner = THIS_MODULE; 231295711cd5SPawel Dembicki vsc->gc.parent = vsc->dev; 231395711cd5SPawel Dembicki vsc->gc.base = -1; 231495711cd5SPawel Dembicki vsc->gc.get = vsc73xx_gpio_get; 231595711cd5SPawel Dembicki vsc->gc.set = vsc73xx_gpio_set; 231695711cd5SPawel Dembicki vsc->gc.direction_input = vsc73xx_gpio_direction_input; 231795711cd5SPawel Dembicki vsc->gc.direction_output = vsc73xx_gpio_direction_output; 231895711cd5SPawel Dembicki vsc->gc.get_direction = vsc73xx_gpio_get_direction; 231995711cd5SPawel Dembicki vsc->gc.can_sleep = true; 232095711cd5SPawel Dembicki ret = devm_gpiochip_add_data(vsc->dev, &vsc->gc, vsc); 232195711cd5SPawel Dembicki if (ret) { 232295711cd5SPawel Dembicki dev_err(vsc->dev, "unable to register GPIO chip\n"); 232395711cd5SPawel Dembicki return ret; 232495711cd5SPawel Dembicki } 232595711cd5SPawel Dembicki return 0; 232695711cd5SPawel Dembicki } 232795711cd5SPawel Dembicki 232895711cd5SPawel Dembicki int vsc73xx_probe(struct vsc73xx *vsc) 232995711cd5SPawel Dembicki { 233095711cd5SPawel Dembicki struct device *dev = vsc->dev; 233195711cd5SPawel Dembicki int ret; 233295711cd5SPawel Dembicki 233395711cd5SPawel Dembicki /* Release reset, if any */ 233495711cd5SPawel Dembicki vsc->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); 233595711cd5SPawel Dembicki if (IS_ERR(vsc->reset)) { 233695711cd5SPawel Dembicki dev_err(dev, "failed to get RESET GPIO\n"); 233795711cd5SPawel Dembicki return PTR_ERR(vsc->reset); 233895711cd5SPawel Dembicki } 233995711cd5SPawel Dembicki if (vsc->reset) 234095711cd5SPawel Dembicki /* Wait 20ms according to datasheet table 245 */ 234195711cd5SPawel Dembicki msleep(20); 234295711cd5SPawel Dembicki 234395711cd5SPawel Dembicki ret = vsc73xx_detect(vsc); 23441da39ff0SPawel Dembicki if (ret == -EAGAIN) { 23451da39ff0SPawel Dembicki dev_err(vsc->dev, 23461da39ff0SPawel Dembicki "Chip seems to be out of control. Assert reset and try again.\n"); 23471da39ff0SPawel Dembicki gpiod_set_value_cansleep(vsc->reset, 1); 23481da39ff0SPawel Dembicki /* Reset pulse should be 20ns minimum, according to datasheet 23491da39ff0SPawel Dembicki * table 245, so 10us should be fine 23501da39ff0SPawel Dembicki */ 23511da39ff0SPawel Dembicki usleep_range(10, 100); 23521da39ff0SPawel Dembicki gpiod_set_value_cansleep(vsc->reset, 0); 23531da39ff0SPawel Dembicki /* Wait 20ms according to datasheet table 245 */ 23541da39ff0SPawel Dembicki msleep(20); 23551da39ff0SPawel Dembicki ret = vsc73xx_detect(vsc); 23561da39ff0SPawel Dembicki } 235795711cd5SPawel Dembicki if (ret) { 235895711cd5SPawel Dembicki dev_err(dev, "no chip found (%d)\n", ret); 235995711cd5SPawel Dembicki return -ENODEV; 236095711cd5SPawel Dembicki } 236195711cd5SPawel Dembicki 2362*075e3d30SPawel Dembicki mutex_init(&vsc->fdb_lock); 2363*075e3d30SPawel Dembicki 236495711cd5SPawel Dembicki eth_random_addr(vsc->addr); 236595711cd5SPawel Dembicki dev_info(vsc->dev, 236695711cd5SPawel Dembicki "MAC for control frames: %02X:%02X:%02X:%02X:%02X:%02X\n", 236795711cd5SPawel Dembicki vsc->addr[0], vsc->addr[1], vsc->addr[2], 236895711cd5SPawel Dembicki vsc->addr[3], vsc->addr[4], vsc->addr[5]); 236995711cd5SPawel Dembicki 23707e99e347SVivien Didelot vsc->ds = devm_kzalloc(dev, sizeof(*vsc->ds), GFP_KERNEL); 237195711cd5SPawel Dembicki if (!vsc->ds) 237295711cd5SPawel Dembicki return -ENOMEM; 23737e99e347SVivien Didelot 23747e99e347SVivien Didelot vsc->ds->dev = dev; 23756cc5280aSPawel Dembicki vsc->ds->num_ports = VSC73XX_MAX_NUM_PORTS; 237695711cd5SPawel Dembicki vsc->ds->priv = vsc; 237795711cd5SPawel Dembicki 237895711cd5SPawel Dembicki vsc->ds->ops = &vsc73xx_ds_ops; 237921fc3416SPawel Dembicki vsc->ds->phylink_mac_ops = &vsc73xx_phylink_mac_ops; 238095711cd5SPawel Dembicki ret = dsa_register_switch(vsc->ds); 238195711cd5SPawel Dembicki if (ret) { 238295711cd5SPawel Dembicki dev_err(dev, "unable to register switch (%d)\n", ret); 238395711cd5SPawel Dembicki return ret; 238495711cd5SPawel Dembicki } 238595711cd5SPawel Dembicki 238695711cd5SPawel Dembicki ret = vsc73xx_gpio_probe(vsc); 238795711cd5SPawel Dembicki if (ret) { 238895711cd5SPawel Dembicki dsa_unregister_switch(vsc->ds); 238995711cd5SPawel Dembicki return ret; 239095711cd5SPawel Dembicki } 239195711cd5SPawel Dembicki 239295711cd5SPawel Dembicki return 0; 239395711cd5SPawel Dembicki } 239495711cd5SPawel Dembicki EXPORT_SYMBOL(vsc73xx_probe); 239595711cd5SPawel Dembicki 2396e99fa423SUwe Kleine-König void vsc73xx_remove(struct vsc73xx *vsc) 239795711cd5SPawel Dembicki { 239895711cd5SPawel Dembicki dsa_unregister_switch(vsc->ds); 239995711cd5SPawel Dembicki gpiod_set_value(vsc->reset, 1); 240095711cd5SPawel Dembicki } 240195711cd5SPawel Dembicki EXPORT_SYMBOL(vsc73xx_remove); 240295711cd5SPawel Dembicki 24030650bf52SVladimir Oltean void vsc73xx_shutdown(struct vsc73xx *vsc) 24040650bf52SVladimir Oltean { 24050650bf52SVladimir Oltean dsa_switch_shutdown(vsc->ds); 24060650bf52SVladimir Oltean } 24070650bf52SVladimir Oltean EXPORT_SYMBOL(vsc73xx_shutdown); 24080650bf52SVladimir Oltean 240995711cd5SPawel Dembicki MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); 241095711cd5SPawel Dembicki MODULE_DESCRIPTION("Vitesse VSC7385/7388/7395/7398 driver"); 241195711cd5SPawel Dembicki MODULE_LICENSE("GPL v2"); 2412