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> 2495711cd5SPawel Dembicki #include <linux/if_bridge.h> 256b783dedSPawel Dembicki #include <linux/if_vlan.h> 2695711cd5SPawel Dembicki #include <linux/etherdevice.h> 2795711cd5SPawel Dembicki #include <linux/gpio/consumer.h> 2895711cd5SPawel Dembicki #include <linux/gpio/driver.h> 296b783dedSPawel Dembicki #include <linux/dsa/8021q.h> 3095711cd5SPawel Dembicki #include <linux/random.h> 3195711cd5SPawel Dembicki #include <net/dsa.h> 3295711cd5SPawel Dembicki 3395711cd5SPawel Dembicki #include "vitesse-vsc73xx.h" 3495711cd5SPawel Dembicki 3595711cd5SPawel Dembicki #define VSC73XX_BLOCK_MAC 0x1 /* Subblocks 0-4, 6 (CPU port) */ 3695711cd5SPawel Dembicki #define VSC73XX_BLOCK_ANALYZER 0x2 /* Only subblock 0 */ 3795711cd5SPawel Dembicki #define VSC73XX_BLOCK_MII 0x3 /* Subblocks 0 and 1 */ 3895711cd5SPawel Dembicki #define VSC73XX_BLOCK_MEMINIT 0x3 /* Only subblock 2 */ 3995711cd5SPawel Dembicki #define VSC73XX_BLOCK_CAPTURE 0x4 /* Only subblock 2 */ 4095711cd5SPawel Dembicki #define VSC73XX_BLOCK_ARBITER 0x5 /* Only subblock 0 */ 4195711cd5SPawel Dembicki #define VSC73XX_BLOCK_SYSTEM 0x7 /* Only subblock 0 */ 4295711cd5SPawel Dembicki 4395711cd5SPawel Dembicki #define CPU_PORT 6 /* CPU port */ 4495711cd5SPawel Dembicki 4595711cd5SPawel Dembicki /* MAC Block registers */ 4695711cd5SPawel Dembicki #define VSC73XX_MAC_CFG 0x00 4795711cd5SPawel Dembicki #define VSC73XX_MACHDXGAP 0x02 4895711cd5SPawel Dembicki #define VSC73XX_FCCONF 0x04 4995711cd5SPawel Dembicki #define VSC73XX_FCMACHI 0x08 5095711cd5SPawel Dembicki #define VSC73XX_FCMACLO 0x0c 5195711cd5SPawel Dembicki #define VSC73XX_MAXLEN 0x10 5295711cd5SPawel Dembicki #define VSC73XX_ADVPORTM 0x19 5395711cd5SPawel Dembicki #define VSC73XX_TXUPDCFG 0x24 5495711cd5SPawel Dembicki #define VSC73XX_TXQ_SELECT_CFG 0x28 5595711cd5SPawel Dembicki #define VSC73XX_RXOCT 0x50 5695711cd5SPawel Dembicki #define VSC73XX_TXOCT 0x51 5795711cd5SPawel Dembicki #define VSC73XX_C_RX0 0x52 5895711cd5SPawel Dembicki #define VSC73XX_C_RX1 0x53 5995711cd5SPawel Dembicki #define VSC73XX_C_RX2 0x54 6095711cd5SPawel Dembicki #define VSC73XX_C_TX0 0x55 6195711cd5SPawel Dembicki #define VSC73XX_C_TX1 0x56 6295711cd5SPawel Dembicki #define VSC73XX_C_TX2 0x57 6395711cd5SPawel Dembicki #define VSC73XX_C_CFG 0x58 6495711cd5SPawel Dembicki #define VSC73XX_CAT_DROP 0x6e 6595711cd5SPawel Dembicki #define VSC73XX_CAT_PR_MISC_L2 0x6f 6695711cd5SPawel Dembicki #define VSC73XX_CAT_PR_USR_PRIO 0x75 676b783dedSPawel Dembicki #define VSC73XX_CAT_VLAN_MISC 0x79 686b783dedSPawel Dembicki #define VSC73XX_CAT_PORT_VLAN 0x7a 6995711cd5SPawel Dembicki #define VSC73XX_Q_MISC_CONF 0xdf 7095711cd5SPawel Dembicki 7195711cd5SPawel Dembicki /* MAC_CFG register bits */ 7295711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_WEXC_DIS BIT(31) 7395711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_PORT_RST BIT(29) 7495711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_TX_EN BIT(28) 7595711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_SEED_LOAD BIT(27) 7695711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_SEED_MASK GENMASK(26, 19) 7795711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_SEED_OFFSET 19 7895711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_FDX BIT(18) 7995711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_GIGA_MODE BIT(17) 8095711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_RX_EN BIT(16) 8195711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_VLAN_DBLAWR BIT(15) 8295711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_VLAN_AWR BIT(14) 8395711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_100_BASE_T BIT(13) /* Not in manual */ 8495711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_TX_IPG_MASK GENMASK(10, 6) 8595711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_TX_IPG_OFFSET 6 8695711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_TX_IPG_1000M (6 << VSC73XX_MAC_CFG_TX_IPG_OFFSET) 8795711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_TX_IPG_100_10M (17 << VSC73XX_MAC_CFG_TX_IPG_OFFSET) 8895711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_MAC_RX_RST BIT(5) 8995711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_MAC_TX_RST BIT(4) 9095711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_CLK_SEL_MASK GENMASK(2, 0) 9195711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_CLK_SEL_OFFSET 0 9295711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_CLK_SEL_1000M 1 9395711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_CLK_SEL_100M 2 9495711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_CLK_SEL_10M 3 9595711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_CLK_SEL_EXT 4 9695711cd5SPawel Dembicki 9795711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_1000M_F_PHY (VSC73XX_MAC_CFG_FDX | \ 9895711cd5SPawel Dembicki VSC73XX_MAC_CFG_GIGA_MODE | \ 9995711cd5SPawel Dembicki VSC73XX_MAC_CFG_TX_IPG_1000M | \ 10095711cd5SPawel Dembicki VSC73XX_MAC_CFG_CLK_SEL_EXT) 10195711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_100_10M_F_PHY (VSC73XX_MAC_CFG_FDX | \ 10295711cd5SPawel Dembicki VSC73XX_MAC_CFG_TX_IPG_100_10M | \ 10395711cd5SPawel Dembicki VSC73XX_MAC_CFG_CLK_SEL_EXT) 10495711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_100_10M_H_PHY (VSC73XX_MAC_CFG_TX_IPG_100_10M | \ 10595711cd5SPawel Dembicki VSC73XX_MAC_CFG_CLK_SEL_EXT) 10695711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_1000M_F_RGMII (VSC73XX_MAC_CFG_FDX | \ 10795711cd5SPawel Dembicki VSC73XX_MAC_CFG_GIGA_MODE | \ 10895711cd5SPawel Dembicki VSC73XX_MAC_CFG_TX_IPG_1000M | \ 10995711cd5SPawel Dembicki VSC73XX_MAC_CFG_CLK_SEL_1000M) 11095711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_RESET (VSC73XX_MAC_CFG_PORT_RST | \ 11195711cd5SPawel Dembicki VSC73XX_MAC_CFG_MAC_RX_RST | \ 11295711cd5SPawel Dembicki VSC73XX_MAC_CFG_MAC_TX_RST) 11395711cd5SPawel Dembicki 11495711cd5SPawel Dembicki /* Flow control register bits */ 11595711cd5SPawel Dembicki #define VSC73XX_FCCONF_ZERO_PAUSE_EN BIT(17) 11695711cd5SPawel Dembicki #define VSC73XX_FCCONF_FLOW_CTRL_OBEY BIT(16) 11795711cd5SPawel Dembicki #define VSC73XX_FCCONF_PAUSE_VAL_MASK GENMASK(15, 0) 11895711cd5SPawel Dembicki 11995711cd5SPawel Dembicki /* ADVPORTM advanced port setup register bits */ 12095711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_IFG_PPM BIT(7) 12195711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_EXC_COL_CONT BIT(6) 12295711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_EXT_PORT BIT(5) 12395711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_INV_GTX BIT(4) 12495711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_ENA_GTX BIT(3) 12595711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_DDR_MODE BIT(2) 12695711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_IO_LOOPBACK BIT(1) 12795711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_HOST_LOOPBACK BIT(0) 12895711cd5SPawel Dembicki 1296b783dedSPawel Dembicki /* TXUPDCFG transmit modify setup bits */ 1306b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_DSCP_REWR_MODE GENMASK(20, 19) 1316b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_DSCP_REWR_ENA BIT(18) 1326b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_TX_INT_TO_USRPRIO_ENA BIT(17) 1336b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_TX_UNTAGGED_VID GENMASK(15, 4) 1346b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_TX_UNTAGGED_VID_ENA BIT(3) 1356b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_TX_UPDATE_CRC_CPU_ENA BIT(1) 1366b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_TX_INSERT_TAG BIT(0) 1376b783dedSPawel Dembicki 1386b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_TX_UNTAGGED_VID_SHIFT 4 1396b783dedSPawel Dembicki 14095711cd5SPawel Dembicki /* CAT_DROP categorizer frame dropping register bits */ 14195711cd5SPawel Dembicki #define VSC73XX_CAT_DROP_DROP_MC_SMAC_ENA BIT(6) 14295711cd5SPawel Dembicki #define VSC73XX_CAT_DROP_FWD_CTRL_ENA BIT(4) 14395711cd5SPawel Dembicki #define VSC73XX_CAT_DROP_FWD_PAUSE_ENA BIT(3) 14495711cd5SPawel Dembicki #define VSC73XX_CAT_DROP_UNTAGGED_ENA BIT(2) 14595711cd5SPawel Dembicki #define VSC73XX_CAT_DROP_TAGGED_ENA BIT(1) 14695711cd5SPawel Dembicki #define VSC73XX_CAT_DROP_NULL_MAC_ENA BIT(0) 14795711cd5SPawel Dembicki 14895711cd5SPawel Dembicki #define VSC73XX_Q_MISC_CONF_EXTENT_MEM BIT(31) 14995711cd5SPawel Dembicki #define VSC73XX_Q_MISC_CONF_EARLY_TX_MASK GENMASK(4, 1) 15095711cd5SPawel Dembicki #define VSC73XX_Q_MISC_CONF_EARLY_TX_512 (1 << 1) 15195711cd5SPawel Dembicki #define VSC73XX_Q_MISC_CONF_MAC_PAUSE_MODE BIT(0) 15295711cd5SPawel Dembicki 1536b783dedSPawel Dembicki /* CAT_VLAN_MISC categorizer VLAN miscellaneous bits */ 1546b783dedSPawel Dembicki #define VSC73XX_CAT_VLAN_MISC_VLAN_TCI_IGNORE_ENA BIT(8) 1556b783dedSPawel Dembicki #define VSC73XX_CAT_VLAN_MISC_VLAN_KEEP_TAG_ENA BIT(7) 1566b783dedSPawel Dembicki 1576b783dedSPawel Dembicki /* CAT_PORT_VLAN categorizer port VLAN */ 1586b783dedSPawel Dembicki #define VSC73XX_CAT_PORT_VLAN_VLAN_CFI BIT(15) 1596b783dedSPawel Dembicki #define VSC73XX_CAT_PORT_VLAN_VLAN_USR_PRIO GENMASK(14, 12) 1606b783dedSPawel Dembicki #define VSC73XX_CAT_PORT_VLAN_VLAN_VID GENMASK(11, 0) 1616b783dedSPawel Dembicki 16295711cd5SPawel Dembicki /* Frame analyzer block 2 registers */ 16395711cd5SPawel Dembicki #define VSC73XX_STORMLIMIT 0x02 16495711cd5SPawel Dembicki #define VSC73XX_ADVLEARN 0x03 16595711cd5SPawel Dembicki #define VSC73XX_IFLODMSK 0x04 16695711cd5SPawel Dembicki #define VSC73XX_VLANMASK 0x05 16795711cd5SPawel Dembicki #define VSC73XX_MACHDATA 0x06 16895711cd5SPawel Dembicki #define VSC73XX_MACLDATA 0x07 16995711cd5SPawel Dembicki #define VSC73XX_ANMOVED 0x08 17095711cd5SPawel Dembicki #define VSC73XX_ANAGEFIL 0x09 17195711cd5SPawel Dembicki #define VSC73XX_ANEVENTS 0x0a 17295711cd5SPawel Dembicki #define VSC73XX_ANCNTMASK 0x0b 17395711cd5SPawel Dembicki #define VSC73XX_ANCNTVAL 0x0c 17495711cd5SPawel Dembicki #define VSC73XX_LEARNMASK 0x0d 17595711cd5SPawel Dembicki #define VSC73XX_UFLODMASK 0x0e 17695711cd5SPawel Dembicki #define VSC73XX_MFLODMASK 0x0f 17795711cd5SPawel Dembicki #define VSC73XX_RECVMASK 0x10 17895711cd5SPawel Dembicki #define VSC73XX_AGGRCTRL 0x20 17995711cd5SPawel Dembicki #define VSC73XX_AGGRMSKS 0x30 /* Until 0x3f */ 18095711cd5SPawel Dembicki #define VSC73XX_DSTMASKS 0x40 /* Until 0x7f */ 18195711cd5SPawel Dembicki #define VSC73XX_SRCMASKS 0x80 /* Until 0x87 */ 18295711cd5SPawel Dembicki #define VSC73XX_CAPENAB 0xa0 18395711cd5SPawel Dembicki #define VSC73XX_MACACCESS 0xb0 18495711cd5SPawel Dembicki #define VSC73XX_IPMCACCESS 0xb1 18595711cd5SPawel Dembicki #define VSC73XX_MACTINDX 0xc0 18695711cd5SPawel Dembicki #define VSC73XX_VLANACCESS 0xd0 18795711cd5SPawel Dembicki #define VSC73XX_VLANTIDX 0xe0 18895711cd5SPawel Dembicki #define VSC73XX_AGENCTRL 0xf0 18995711cd5SPawel Dembicki #define VSC73XX_CAPRST 0xff 19095711cd5SPawel Dembicki 1911e5b23e5SPawel Dembicki #define VSC73XX_SRCMASKS_CPU_COPY BIT(27) 1921e5b23e5SPawel Dembicki #define VSC73XX_SRCMASKS_MIRROR BIT(26) 1931e5b23e5SPawel Dembicki #define VSC73XX_SRCMASKS_PORTS_MASK GENMASK(7, 0) 1941e5b23e5SPawel Dembicki 19595711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CPU_COPY BIT(14) 19695711cd5SPawel Dembicki #define VSC73XX_MACACCESS_FWD_KILL BIT(13) 19795711cd5SPawel Dembicki #define VSC73XX_MACACCESS_IGNORE_VLAN BIT(12) 19895711cd5SPawel Dembicki #define VSC73XX_MACACCESS_AGED_FLAG BIT(11) 19995711cd5SPawel Dembicki #define VSC73XX_MACACCESS_VALID BIT(10) 20095711cd5SPawel Dembicki #define VSC73XX_MACACCESS_LOCKED BIT(9) 20195711cd5SPawel Dembicki #define VSC73XX_MACACCESS_DEST_IDX_MASK GENMASK(8, 3) 20295711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_MASK GENMASK(2, 0) 20395711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_IDLE 0 20495711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_LEARN 1 20595711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_FORGET 2 20695711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_AGE_TABLE 3 20795711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_FLUSH_TABLE 4 20895711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_CLEAR_TABLE 5 20995711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_READ_ENTRY 6 21095711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_WRITE_ENTRY 7 21195711cd5SPawel Dembicki 21295711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_LEARN_DISABLED BIT(30) 21395711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_MIRROR BIT(29) 21495711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_SRC_CHECK BIT(28) 21595711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_PORT_MASK GENMASK(9, 2) 2166b783dedSPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_PORT_MASK_SHIFT 2 2176b783dedSPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_MASK GENMASK(1, 0) 21895711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_IDLE 0 21995711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_READ_ENTRY 1 22095711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_WRITE_ENTRY 2 22195711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_CLEAR_TABLE 3 22295711cd5SPawel Dembicki 22395711cd5SPawel Dembicki /* MII block 3 registers */ 22495711cd5SPawel Dembicki #define VSC73XX_MII_STAT 0x0 22595711cd5SPawel Dembicki #define VSC73XX_MII_CMD 0x1 22695711cd5SPawel Dembicki #define VSC73XX_MII_DATA 0x2 22795711cd5SPawel Dembicki 22895711cd5SPawel Dembicki /* Arbiter block 5 registers */ 22995711cd5SPawel Dembicki #define VSC73XX_ARBEMPTY 0x0c 23095711cd5SPawel Dembicki #define VSC73XX_ARBDISC 0x0e 23195711cd5SPawel Dembicki #define VSC73XX_SBACKWDROP 0x12 23295711cd5SPawel Dembicki #define VSC73XX_DBACKWDROP 0x13 23395711cd5SPawel Dembicki #define VSC73XX_ARBBURSTPROB 0x15 23495711cd5SPawel Dembicki 23595711cd5SPawel Dembicki /* System block 7 registers */ 23695711cd5SPawel Dembicki #define VSC73XX_ICPU_SIPAD 0x01 23795711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY 0x05 23895711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL 0x10 23995711cd5SPawel Dembicki #define VSC73XX_ICPU_ADDR 0x11 24095711cd5SPawel Dembicki #define VSC73XX_ICPU_SRAM 0x12 24195711cd5SPawel Dembicki #define VSC73XX_HWSEM 0x13 24295711cd5SPawel Dembicki #define VSC73XX_GLORESET 0x14 24395711cd5SPawel Dembicki #define VSC73XX_ICPU_MBOX_VAL 0x15 24495711cd5SPawel Dembicki #define VSC73XX_ICPU_MBOX_SET 0x16 24595711cd5SPawel Dembicki #define VSC73XX_ICPU_MBOX_CLR 0x17 24695711cd5SPawel Dembicki #define VSC73XX_CHIPID 0x18 24795711cd5SPawel Dembicki #define VSC73XX_GPIO 0x34 24895711cd5SPawel Dembicki 24995711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_GTXDELAY_NONE 0 25095711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_GTXDELAY_1_4_NS 1 25195711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_GTXDELAY_1_7_NS 2 25295711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_GTXDELAY_2_0_NS 3 25395711cd5SPawel Dembicki 25495711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_RXDELAY_NONE (0 << 4) 25595711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_RXDELAY_1_4_NS (1 << 4) 25695711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_RXDELAY_1_7_NS (2 << 4) 25795711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_RXDELAY_2_0_NS (3 << 4) 25895711cd5SPawel Dembicki 25995711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_WATCHDOG_RST BIT(31) 26095711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_CLK_DIV_MASK GENMASK(12, 8) 26195711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_SRST_HOLD BIT(7) 26295711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_ICPU_PI_EN BIT(6) 26395711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_BOOT_EN BIT(3) 26495711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_EXT_ACC_EN BIT(2) 26595711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_CLK_EN BIT(1) 26695711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_SRST BIT(0) 26795711cd5SPawel Dembicki 26895711cd5SPawel Dembicki #define VSC73XX_CHIPID_ID_SHIFT 12 26995711cd5SPawel Dembicki #define VSC73XX_CHIPID_ID_MASK 0xffff 27095711cd5SPawel Dembicki #define VSC73XX_CHIPID_REV_SHIFT 28 27195711cd5SPawel Dembicki #define VSC73XX_CHIPID_REV_MASK 0xf 27295711cd5SPawel Dembicki #define VSC73XX_CHIPID_ID_7385 0x7385 27395711cd5SPawel Dembicki #define VSC73XX_CHIPID_ID_7388 0x7388 27495711cd5SPawel Dembicki #define VSC73XX_CHIPID_ID_7395 0x7395 27595711cd5SPawel Dembicki #define VSC73XX_CHIPID_ID_7398 0x7398 27695711cd5SPawel Dembicki 27795711cd5SPawel Dembicki #define VSC73XX_GLORESET_STROBE BIT(4) 27895711cd5SPawel Dembicki #define VSC73XX_GLORESET_ICPU_LOCK BIT(3) 27995711cd5SPawel Dembicki #define VSC73XX_GLORESET_MEM_LOCK BIT(2) 28095711cd5SPawel Dembicki #define VSC73XX_GLORESET_PHY_RESET BIT(1) 28195711cd5SPawel Dembicki #define VSC73XX_GLORESET_MASTER_RESET BIT(0) 28295711cd5SPawel Dembicki 28395711cd5SPawel Dembicki #define VSC7385_CLOCK_DELAY ((3 << 4) | 3) 28495711cd5SPawel Dembicki #define VSC7385_CLOCK_DELAY_MASK ((3 << 4) | 3) 28595711cd5SPawel Dembicki 28695711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_STOP (VSC73XX_ICPU_CTRL_SRST_HOLD | \ 28795711cd5SPawel Dembicki VSC73XX_ICPU_CTRL_BOOT_EN | \ 28895711cd5SPawel Dembicki VSC73XX_ICPU_CTRL_EXT_ACC_EN) 28995711cd5SPawel Dembicki 29095711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_START (VSC73XX_ICPU_CTRL_CLK_DIV | \ 29195711cd5SPawel Dembicki VSC73XX_ICPU_CTRL_BOOT_EN | \ 29295711cd5SPawel Dembicki VSC73XX_ICPU_CTRL_CLK_EN | \ 29395711cd5SPawel Dembicki VSC73XX_ICPU_CTRL_SRST) 29495711cd5SPawel Dembicki 29595711cd5SPawel Dembicki #define IS_7385(a) ((a)->chipid == VSC73XX_CHIPID_ID_7385) 29695711cd5SPawel Dembicki #define IS_7388(a) ((a)->chipid == VSC73XX_CHIPID_ID_7388) 29795711cd5SPawel Dembicki #define IS_7395(a) ((a)->chipid == VSC73XX_CHIPID_ID_7395) 29895711cd5SPawel Dembicki #define IS_7398(a) ((a)->chipid == VSC73XX_CHIPID_ID_7398) 29995711cd5SPawel Dembicki #define IS_739X(a) (IS_7395(a) || IS_7398(a)) 30095711cd5SPawel Dembicki 301eb7e33d0SPawel Dembicki #define VSC73XX_POLL_SLEEP_US 1000 302eb7e33d0SPawel Dembicki #define VSC73XX_POLL_TIMEOUT_US 10000 303eb7e33d0SPawel Dembicki 30495711cd5SPawel Dembicki struct vsc73xx_counter { 30595711cd5SPawel Dembicki u8 counter; 30695711cd5SPawel Dembicki const char *name; 30795711cd5SPawel Dembicki }; 30895711cd5SPawel Dembicki 30995711cd5SPawel Dembicki /* Counters are named according to the MIB standards where applicable. 31095711cd5SPawel Dembicki * Some counters are custom, non-standard. The standard counters are 31195711cd5SPawel Dembicki * named in accordance with RFC2819, RFC2021 and IEEE Std 802.3-2002 Annex 31295711cd5SPawel Dembicki * 30A Counters. 31395711cd5SPawel Dembicki */ 31495711cd5SPawel Dembicki static const struct vsc73xx_counter vsc73xx_rx_counters[] = { 31595711cd5SPawel Dembicki { 0, "RxEtherStatsPkts" }, 31695711cd5SPawel Dembicki { 1, "RxBroadcast+MulticastPkts" }, /* non-standard counter */ 31795711cd5SPawel Dembicki { 2, "RxTotalErrorPackets" }, /* non-standard counter */ 31895711cd5SPawel Dembicki { 3, "RxEtherStatsBroadcastPkts" }, 31995711cd5SPawel Dembicki { 4, "RxEtherStatsMulticastPkts" }, 32095711cd5SPawel Dembicki { 5, "RxEtherStatsPkts64Octets" }, 32195711cd5SPawel Dembicki { 6, "RxEtherStatsPkts65to127Octets" }, 32295711cd5SPawel Dembicki { 7, "RxEtherStatsPkts128to255Octets" }, 32395711cd5SPawel Dembicki { 8, "RxEtherStatsPkts256to511Octets" }, 32495711cd5SPawel Dembicki { 9, "RxEtherStatsPkts512to1023Octets" }, 32595711cd5SPawel Dembicki { 10, "RxEtherStatsPkts1024to1518Octets" }, 32695711cd5SPawel Dembicki { 11, "RxJumboFrames" }, /* non-standard counter */ 32795711cd5SPawel Dembicki { 12, "RxaPauseMACControlFramesTransmitted" }, 32895711cd5SPawel Dembicki { 13, "RxFIFODrops" }, /* non-standard counter */ 32995711cd5SPawel Dembicki { 14, "RxBackwardDrops" }, /* non-standard counter */ 33095711cd5SPawel Dembicki { 15, "RxClassifierDrops" }, /* non-standard counter */ 33195711cd5SPawel Dembicki { 16, "RxEtherStatsCRCAlignErrors" }, 33295711cd5SPawel Dembicki { 17, "RxEtherStatsUndersizePkts" }, 33395711cd5SPawel Dembicki { 18, "RxEtherStatsOversizePkts" }, 33495711cd5SPawel Dembicki { 19, "RxEtherStatsFragments" }, 33595711cd5SPawel Dembicki { 20, "RxEtherStatsJabbers" }, 33695711cd5SPawel Dembicki { 21, "RxaMACControlFramesReceived" }, 33795711cd5SPawel Dembicki /* 22-24 are undefined */ 33895711cd5SPawel Dembicki { 25, "RxaFramesReceivedOK" }, 33995711cd5SPawel Dembicki { 26, "RxQoSClass0" }, /* non-standard counter */ 34095711cd5SPawel Dembicki { 27, "RxQoSClass1" }, /* non-standard counter */ 34195711cd5SPawel Dembicki { 28, "RxQoSClass2" }, /* non-standard counter */ 34295711cd5SPawel Dembicki { 29, "RxQoSClass3" }, /* non-standard counter */ 34395711cd5SPawel Dembicki }; 34495711cd5SPawel Dembicki 34595711cd5SPawel Dembicki static const struct vsc73xx_counter vsc73xx_tx_counters[] = { 34695711cd5SPawel Dembicki { 0, "TxEtherStatsPkts" }, 34795711cd5SPawel Dembicki { 1, "TxBroadcast+MulticastPkts" }, /* non-standard counter */ 34895711cd5SPawel Dembicki { 2, "TxTotalErrorPackets" }, /* non-standard counter */ 34995711cd5SPawel Dembicki { 3, "TxEtherStatsBroadcastPkts" }, 35095711cd5SPawel Dembicki { 4, "TxEtherStatsMulticastPkts" }, 35195711cd5SPawel Dembicki { 5, "TxEtherStatsPkts64Octets" }, 35295711cd5SPawel Dembicki { 6, "TxEtherStatsPkts65to127Octets" }, 35395711cd5SPawel Dembicki { 7, "TxEtherStatsPkts128to255Octets" }, 35495711cd5SPawel Dembicki { 8, "TxEtherStatsPkts256to511Octets" }, 35595711cd5SPawel Dembicki { 9, "TxEtherStatsPkts512to1023Octets" }, 35695711cd5SPawel Dembicki { 10, "TxEtherStatsPkts1024to1518Octets" }, 35795711cd5SPawel Dembicki { 11, "TxJumboFrames" }, /* non-standard counter */ 35895711cd5SPawel Dembicki { 12, "TxaPauseMACControlFramesTransmitted" }, 35995711cd5SPawel Dembicki { 13, "TxFIFODrops" }, /* non-standard counter */ 36095711cd5SPawel Dembicki { 14, "TxDrops" }, /* non-standard counter */ 36195711cd5SPawel Dembicki { 15, "TxEtherStatsCollisions" }, 36295711cd5SPawel Dembicki { 16, "TxEtherStatsCRCAlignErrors" }, 36395711cd5SPawel Dembicki { 17, "TxEtherStatsUndersizePkts" }, 36495711cd5SPawel Dembicki { 18, "TxEtherStatsOversizePkts" }, 36595711cd5SPawel Dembicki { 19, "TxEtherStatsFragments" }, 36695711cd5SPawel Dembicki { 20, "TxEtherStatsJabbers" }, 36795711cd5SPawel Dembicki /* 21-24 are undefined */ 36895711cd5SPawel Dembicki { 25, "TxaFramesReceivedOK" }, 36995711cd5SPawel Dembicki { 26, "TxQoSClass0" }, /* non-standard counter */ 37095711cd5SPawel Dembicki { 27, "TxQoSClass1" }, /* non-standard counter */ 37195711cd5SPawel Dembicki { 28, "TxQoSClass2" }, /* non-standard counter */ 37295711cd5SPawel Dembicki { 29, "TxQoSClass3" }, /* non-standard counter */ 37395711cd5SPawel Dembicki }; 37495711cd5SPawel Dembicki 3756b783dedSPawel Dembicki struct vsc73xx_vlan_summary { 3766b783dedSPawel Dembicki size_t num_tagged; 3776b783dedSPawel Dembicki size_t num_untagged; 3786b783dedSPawel Dembicki }; 3796b783dedSPawel Dembicki 3806b783dedSPawel Dembicki enum vsc73xx_port_vlan_conf { 3816b783dedSPawel Dembicki VSC73XX_VLAN_FILTER, 3826b783dedSPawel Dembicki VSC73XX_VLAN_FILTER_UNTAG_ALL, 3836b783dedSPawel Dembicki VSC73XX_VLAN_IGNORE, 3846b783dedSPawel Dembicki }; 3856b783dedSPawel Dembicki 38695711cd5SPawel Dembicki int vsc73xx_is_addr_valid(u8 block, u8 subblock) 38795711cd5SPawel Dembicki { 38895711cd5SPawel Dembicki switch (block) { 38995711cd5SPawel Dembicki case VSC73XX_BLOCK_MAC: 39095711cd5SPawel Dembicki switch (subblock) { 39195711cd5SPawel Dembicki case 0 ... 4: 39295711cd5SPawel Dembicki case 6: 39395711cd5SPawel Dembicki return 1; 39495711cd5SPawel Dembicki } 39595711cd5SPawel Dembicki break; 39695711cd5SPawel Dembicki 39795711cd5SPawel Dembicki case VSC73XX_BLOCK_ANALYZER: 39895711cd5SPawel Dembicki case VSC73XX_BLOCK_SYSTEM: 39995711cd5SPawel Dembicki switch (subblock) { 40095711cd5SPawel Dembicki case 0: 40195711cd5SPawel Dembicki return 1; 40295711cd5SPawel Dembicki } 40395711cd5SPawel Dembicki break; 40495711cd5SPawel Dembicki 40595711cd5SPawel Dembicki case VSC73XX_BLOCK_MII: 40695711cd5SPawel Dembicki case VSC73XX_BLOCK_CAPTURE: 40795711cd5SPawel Dembicki case VSC73XX_BLOCK_ARBITER: 40895711cd5SPawel Dembicki switch (subblock) { 40995711cd5SPawel Dembicki case 0 ... 1: 41095711cd5SPawel Dembicki return 1; 41195711cd5SPawel Dembicki } 41295711cd5SPawel Dembicki break; 41395711cd5SPawel Dembicki } 41495711cd5SPawel Dembicki 41595711cd5SPawel Dembicki return 0; 41695711cd5SPawel Dembicki } 41795711cd5SPawel Dembicki EXPORT_SYMBOL(vsc73xx_is_addr_valid); 41895711cd5SPawel Dembicki 41995711cd5SPawel Dembicki static int vsc73xx_read(struct vsc73xx *vsc, u8 block, u8 subblock, u8 reg, 42095711cd5SPawel Dembicki u32 *val) 42195711cd5SPawel Dembicki { 42295711cd5SPawel Dembicki return vsc->ops->read(vsc, block, subblock, reg, val); 42395711cd5SPawel Dembicki } 42495711cd5SPawel Dembicki 42595711cd5SPawel Dembicki static int vsc73xx_write(struct vsc73xx *vsc, u8 block, u8 subblock, u8 reg, 42695711cd5SPawel Dembicki u32 val) 42795711cd5SPawel Dembicki { 42895711cd5SPawel Dembicki return vsc->ops->write(vsc, block, subblock, reg, val); 42995711cd5SPawel Dembicki } 43095711cd5SPawel Dembicki 43195711cd5SPawel Dembicki static int vsc73xx_update_bits(struct vsc73xx *vsc, u8 block, u8 subblock, 43295711cd5SPawel Dembicki u8 reg, u32 mask, u32 val) 43395711cd5SPawel Dembicki { 43495711cd5SPawel Dembicki u32 tmp, orig; 43595711cd5SPawel Dembicki int ret; 43695711cd5SPawel Dembicki 43795711cd5SPawel Dembicki /* Same read-modify-write algorithm as e.g. regmap */ 43895711cd5SPawel Dembicki ret = vsc73xx_read(vsc, block, subblock, reg, &orig); 43995711cd5SPawel Dembicki if (ret) 44095711cd5SPawel Dembicki return ret; 44195711cd5SPawel Dembicki tmp = orig & ~mask; 44295711cd5SPawel Dembicki tmp |= val & mask; 44395711cd5SPawel Dembicki return vsc73xx_write(vsc, block, subblock, reg, tmp); 44495711cd5SPawel Dembicki } 44595711cd5SPawel Dembicki 44695711cd5SPawel Dembicki static int vsc73xx_detect(struct vsc73xx *vsc) 44795711cd5SPawel Dembicki { 44895711cd5SPawel Dembicki bool icpu_si_boot_en; 44995711cd5SPawel Dembicki bool icpu_pi_en; 45095711cd5SPawel Dembicki u32 val; 45195711cd5SPawel Dembicki u32 rev; 45295711cd5SPawel Dembicki int ret; 45395711cd5SPawel Dembicki u32 id; 45495711cd5SPawel Dembicki 45595711cd5SPawel Dembicki ret = vsc73xx_read(vsc, VSC73XX_BLOCK_SYSTEM, 0, 45695711cd5SPawel Dembicki VSC73XX_ICPU_MBOX_VAL, &val); 45795711cd5SPawel Dembicki if (ret) { 45895711cd5SPawel Dembicki dev_err(vsc->dev, "unable to read mailbox (%d)\n", ret); 45995711cd5SPawel Dembicki return ret; 46095711cd5SPawel Dembicki } 46195711cd5SPawel Dembicki 46295711cd5SPawel Dembicki if (val == 0xffffffff) { 4631da39ff0SPawel Dembicki dev_info(vsc->dev, "chip seems dead.\n"); 4641da39ff0SPawel Dembicki return -EAGAIN; 46595711cd5SPawel Dembicki } 46695711cd5SPawel Dembicki 46795711cd5SPawel Dembicki ret = vsc73xx_read(vsc, VSC73XX_BLOCK_SYSTEM, 0, 46895711cd5SPawel Dembicki VSC73XX_CHIPID, &val); 46995711cd5SPawel Dembicki if (ret) { 47095711cd5SPawel Dembicki dev_err(vsc->dev, "unable to read chip id (%d)\n", ret); 47195711cd5SPawel Dembicki return ret; 47295711cd5SPawel Dembicki } 47395711cd5SPawel Dembicki 47495711cd5SPawel Dembicki id = (val >> VSC73XX_CHIPID_ID_SHIFT) & 47595711cd5SPawel Dembicki VSC73XX_CHIPID_ID_MASK; 47695711cd5SPawel Dembicki switch (id) { 47795711cd5SPawel Dembicki case VSC73XX_CHIPID_ID_7385: 47895711cd5SPawel Dembicki case VSC73XX_CHIPID_ID_7388: 47995711cd5SPawel Dembicki case VSC73XX_CHIPID_ID_7395: 48095711cd5SPawel Dembicki case VSC73XX_CHIPID_ID_7398: 48195711cd5SPawel Dembicki break; 48295711cd5SPawel Dembicki default: 48395711cd5SPawel Dembicki dev_err(vsc->dev, "unsupported chip, id=%04x\n", id); 48495711cd5SPawel Dembicki return -ENODEV; 48595711cd5SPawel Dembicki } 48695711cd5SPawel Dembicki 48795711cd5SPawel Dembicki vsc->chipid = id; 48895711cd5SPawel Dembicki rev = (val >> VSC73XX_CHIPID_REV_SHIFT) & 48995711cd5SPawel Dembicki VSC73XX_CHIPID_REV_MASK; 49095711cd5SPawel Dembicki dev_info(vsc->dev, "VSC%04X (rev: %d) switch found\n", id, rev); 49195711cd5SPawel Dembicki 49295711cd5SPawel Dembicki ret = vsc73xx_read(vsc, VSC73XX_BLOCK_SYSTEM, 0, 49395711cd5SPawel Dembicki VSC73XX_ICPU_CTRL, &val); 49495711cd5SPawel Dembicki if (ret) { 49595711cd5SPawel Dembicki dev_err(vsc->dev, "unable to read iCPU control\n"); 49695711cd5SPawel Dembicki return ret; 49795711cd5SPawel Dembicki } 49895711cd5SPawel Dembicki 49995711cd5SPawel Dembicki /* The iCPU can always be used but can boot in different ways. 50095711cd5SPawel Dembicki * If it is initially disabled and has no external memory, 50195711cd5SPawel Dembicki * we are in control and can do whatever we like, else we 50295711cd5SPawel Dembicki * are probably in trouble (we need some way to communicate 50395711cd5SPawel Dembicki * with the running firmware) so we bail out for now. 50495711cd5SPawel Dembicki */ 50595711cd5SPawel Dembicki icpu_pi_en = !!(val & VSC73XX_ICPU_CTRL_ICPU_PI_EN); 50695711cd5SPawel Dembicki icpu_si_boot_en = !!(val & VSC73XX_ICPU_CTRL_BOOT_EN); 50795711cd5SPawel Dembicki if (icpu_si_boot_en && icpu_pi_en) { 50895711cd5SPawel Dembicki dev_err(vsc->dev, 50995711cd5SPawel Dembicki "iCPU enabled boots from SI, has external memory\n"); 51095711cd5SPawel Dembicki dev_err(vsc->dev, "no idea how to deal with this\n"); 51195711cd5SPawel Dembicki return -ENODEV; 51295711cd5SPawel Dembicki } 51395711cd5SPawel Dembicki if (icpu_si_boot_en && !icpu_pi_en) { 51495711cd5SPawel Dembicki dev_err(vsc->dev, 5151da39ff0SPawel Dembicki "iCPU enabled boots from PI/SI, no external memory\n"); 5161da39ff0SPawel Dembicki return -EAGAIN; 51795711cd5SPawel Dembicki } 51895711cd5SPawel Dembicki if (!icpu_si_boot_en && icpu_pi_en) { 51995711cd5SPawel Dembicki dev_err(vsc->dev, 52095711cd5SPawel Dembicki "iCPU enabled, boots from PI external memory\n"); 52195711cd5SPawel Dembicki dev_err(vsc->dev, "no idea how to deal with this\n"); 52295711cd5SPawel Dembicki return -ENODEV; 52395711cd5SPawel Dembicki } 52495711cd5SPawel Dembicki /* !icpu_si_boot_en && !cpu_pi_en */ 52595711cd5SPawel Dembicki dev_info(vsc->dev, "iCPU disabled, no external memory\n"); 52695711cd5SPawel Dembicki 52795711cd5SPawel Dembicki return 0; 52895711cd5SPawel Dembicki } 52995711cd5SPawel Dembicki 53095711cd5SPawel Dembicki static int vsc73xx_phy_read(struct dsa_switch *ds, int phy, int regnum) 53195711cd5SPawel Dembicki { 53295711cd5SPawel Dembicki struct vsc73xx *vsc = ds->priv; 53395711cd5SPawel Dembicki u32 cmd; 53495711cd5SPawel Dembicki u32 val; 53595711cd5SPawel Dembicki int ret; 53695711cd5SPawel Dembicki 53795711cd5SPawel Dembicki /* Setting bit 26 means "read" */ 53895711cd5SPawel Dembicki cmd = BIT(26) | (phy << 21) | (regnum << 16); 53995711cd5SPawel Dembicki ret = vsc73xx_write(vsc, VSC73XX_BLOCK_MII, 0, 1, cmd); 54095711cd5SPawel Dembicki if (ret) 54195711cd5SPawel Dembicki return ret; 54295711cd5SPawel Dembicki msleep(2); 54395711cd5SPawel Dembicki ret = vsc73xx_read(vsc, VSC73XX_BLOCK_MII, 0, 2, &val); 54495711cd5SPawel Dembicki if (ret) 54595711cd5SPawel Dembicki return ret; 54695711cd5SPawel Dembicki if (val & BIT(16)) { 54795711cd5SPawel Dembicki dev_err(vsc->dev, "reading reg %02x from phy%d failed\n", 54895711cd5SPawel Dembicki regnum, phy); 54995711cd5SPawel Dembicki return -EIO; 55095711cd5SPawel Dembicki } 55195711cd5SPawel Dembicki val &= 0xFFFFU; 55295711cd5SPawel Dembicki 55395711cd5SPawel Dembicki dev_dbg(vsc->dev, "read reg %02x from phy%d = %04x\n", 55495711cd5SPawel Dembicki regnum, phy, val); 55595711cd5SPawel Dembicki 55695711cd5SPawel Dembicki return val; 55795711cd5SPawel Dembicki } 55895711cd5SPawel Dembicki 55995711cd5SPawel Dembicki static int vsc73xx_phy_write(struct dsa_switch *ds, int phy, int regnum, 56095711cd5SPawel Dembicki u16 val) 56195711cd5SPawel Dembicki { 56295711cd5SPawel Dembicki struct vsc73xx *vsc = ds->priv; 56395711cd5SPawel Dembicki u32 cmd; 56495711cd5SPawel Dembicki int ret; 56595711cd5SPawel Dembicki 56695711cd5SPawel Dembicki /* It was found through tedious experiments that this router 56795711cd5SPawel Dembicki * chip really hates to have it's PHYs reset. They 56895711cd5SPawel Dembicki * never recover if that happens: autonegotiation stops 56995711cd5SPawel Dembicki * working after a reset. Just filter out this command. 57095711cd5SPawel Dembicki * (Resetting the whole chip is OK.) 57195711cd5SPawel Dembicki */ 57295711cd5SPawel Dembicki if (regnum == 0 && (val & BIT(15))) { 57395711cd5SPawel Dembicki dev_info(vsc->dev, "reset PHY - disallowed\n"); 57495711cd5SPawel Dembicki return 0; 57595711cd5SPawel Dembicki } 57695711cd5SPawel Dembicki 57795711cd5SPawel Dembicki cmd = (phy << 21) | (regnum << 16); 57895711cd5SPawel Dembicki ret = vsc73xx_write(vsc, VSC73XX_BLOCK_MII, 0, 1, cmd); 57995711cd5SPawel Dembicki if (ret) 58095711cd5SPawel Dembicki return ret; 58195711cd5SPawel Dembicki 58295711cd5SPawel Dembicki dev_dbg(vsc->dev, "write %04x to reg %02x in phy%d\n", 58395711cd5SPawel Dembicki val, regnum, phy); 58495711cd5SPawel Dembicki return 0; 58595711cd5SPawel Dembicki } 58695711cd5SPawel Dembicki 58795711cd5SPawel Dembicki static enum dsa_tag_protocol vsc73xx_get_tag_protocol(struct dsa_switch *ds, 5884d776482SFlorian Fainelli int port, 5894d776482SFlorian Fainelli enum dsa_tag_protocol mp) 59095711cd5SPawel Dembicki { 59195711cd5SPawel Dembicki /* The switch internally uses a 8 byte header with length, 59295711cd5SPawel Dembicki * source port, tag, LPA and priority. This is supposedly 59395711cd5SPawel Dembicki * only accessible when operating the switch using the internal 59495711cd5SPawel Dembicki * CPU or with an external CPU mapping the device in, but not 59595711cd5SPawel Dembicki * when operating the switch over SPI and putting frames in/out 59695711cd5SPawel Dembicki * on port 6 (the CPU port). So far we must assume that we 59795711cd5SPawel Dembicki * cannot access the tag. (See "Internal frame header" section 59895711cd5SPawel Dembicki * 3.9.1 in the manual.) 59995711cd5SPawel Dembicki */ 600*e3386ec4SPawel Dembicki return DSA_TAG_PROTO_VSC73XX_8021Q; 60195711cd5SPawel Dembicki } 60295711cd5SPawel Dembicki 6036b783dedSPawel Dembicki static int vsc73xx_wait_for_vlan_table_cmd(struct vsc73xx *vsc) 6046b783dedSPawel Dembicki { 6056b783dedSPawel Dembicki int ret, err; 6066b783dedSPawel Dembicki u32 val; 6076b783dedSPawel Dembicki 6086b783dedSPawel Dembicki ret = read_poll_timeout(vsc73xx_read, err, 6096b783dedSPawel Dembicki err < 0 || 6106b783dedSPawel Dembicki ((val & VSC73XX_VLANACCESS_VLAN_TBL_CMD_MASK) == 6116b783dedSPawel Dembicki VSC73XX_VLANACCESS_VLAN_TBL_CMD_IDLE), 6126b783dedSPawel Dembicki VSC73XX_POLL_SLEEP_US, VSC73XX_POLL_TIMEOUT_US, 6136b783dedSPawel Dembicki false, vsc, VSC73XX_BLOCK_ANALYZER, 6146b783dedSPawel Dembicki 0, VSC73XX_VLANACCESS, &val); 6156b783dedSPawel Dembicki if (ret) 6166b783dedSPawel Dembicki return ret; 6176b783dedSPawel Dembicki return err; 6186b783dedSPawel Dembicki } 6196b783dedSPawel Dembicki 6206b783dedSPawel Dembicki static int 6216b783dedSPawel Dembicki vsc73xx_read_vlan_table_entry(struct vsc73xx *vsc, u16 vid, u8 *portmap) 6226b783dedSPawel Dembicki { 6236b783dedSPawel Dembicki u32 val; 6246b783dedSPawel Dembicki int ret; 6256b783dedSPawel Dembicki 6266b783dedSPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANTIDX, vid); 6276b783dedSPawel Dembicki 6286b783dedSPawel Dembicki ret = vsc73xx_wait_for_vlan_table_cmd(vsc); 6296b783dedSPawel Dembicki if (ret) 6306b783dedSPawel Dembicki return ret; 6316b783dedSPawel Dembicki 6326b783dedSPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANACCESS, 6336b783dedSPawel Dembicki VSC73XX_VLANACCESS_VLAN_TBL_CMD_MASK, 6346b783dedSPawel Dembicki VSC73XX_VLANACCESS_VLAN_TBL_CMD_READ_ENTRY); 6356b783dedSPawel Dembicki 6366b783dedSPawel Dembicki ret = vsc73xx_wait_for_vlan_table_cmd(vsc); 6376b783dedSPawel Dembicki if (ret) 6386b783dedSPawel Dembicki return ret; 6396b783dedSPawel Dembicki 6406b783dedSPawel Dembicki vsc73xx_read(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANACCESS, &val); 6416b783dedSPawel Dembicki *portmap = (val & VSC73XX_VLANACCESS_VLAN_PORT_MASK) >> 6426b783dedSPawel Dembicki VSC73XX_VLANACCESS_VLAN_PORT_MASK_SHIFT; 6436b783dedSPawel Dembicki 6446b783dedSPawel Dembicki return 0; 6456b783dedSPawel Dembicki } 6466b783dedSPawel Dembicki 6476b783dedSPawel Dembicki static int 6486b783dedSPawel Dembicki vsc73xx_write_vlan_table_entry(struct vsc73xx *vsc, u16 vid, u8 portmap) 6496b783dedSPawel Dembicki { 6506b783dedSPawel Dembicki int ret; 6516b783dedSPawel Dembicki 6526b783dedSPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANTIDX, vid); 6536b783dedSPawel Dembicki 6546b783dedSPawel Dembicki ret = vsc73xx_wait_for_vlan_table_cmd(vsc); 6556b783dedSPawel Dembicki if (ret) 6566b783dedSPawel Dembicki return ret; 6576b783dedSPawel Dembicki 6586b783dedSPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANACCESS, 6596b783dedSPawel Dembicki VSC73XX_VLANACCESS_VLAN_TBL_CMD_MASK | 6606b783dedSPawel Dembicki VSC73XX_VLANACCESS_VLAN_SRC_CHECK | 6616b783dedSPawel Dembicki VSC73XX_VLANACCESS_VLAN_PORT_MASK, 6626b783dedSPawel Dembicki VSC73XX_VLANACCESS_VLAN_TBL_CMD_WRITE_ENTRY | 6636b783dedSPawel Dembicki VSC73XX_VLANACCESS_VLAN_SRC_CHECK | 6646b783dedSPawel Dembicki (portmap << VSC73XX_VLANACCESS_VLAN_PORT_MASK_SHIFT)); 6656b783dedSPawel Dembicki 6666b783dedSPawel Dembicki return vsc73xx_wait_for_vlan_table_cmd(vsc); 6676b783dedSPawel Dembicki } 6686b783dedSPawel Dembicki 6696b783dedSPawel Dembicki static int 6706b783dedSPawel Dembicki vsc73xx_update_vlan_table(struct vsc73xx *vsc, int port, u16 vid, bool set) 6716b783dedSPawel Dembicki { 6726b783dedSPawel Dembicki u8 portmap; 6736b783dedSPawel Dembicki int ret; 6746b783dedSPawel Dembicki 6756b783dedSPawel Dembicki ret = vsc73xx_read_vlan_table_entry(vsc, vid, &portmap); 6766b783dedSPawel Dembicki if (ret) 6776b783dedSPawel Dembicki return ret; 6786b783dedSPawel Dembicki 6796b783dedSPawel Dembicki if (set) 6806b783dedSPawel Dembicki portmap |= BIT(port); 6816b783dedSPawel Dembicki else 6826b783dedSPawel Dembicki portmap &= ~BIT(port); 6836b783dedSPawel Dembicki 6846b783dedSPawel Dembicki return vsc73xx_write_vlan_table_entry(vsc, vid, portmap); 6856b783dedSPawel Dembicki } 6866b783dedSPawel Dembicki 68795711cd5SPawel Dembicki static int vsc73xx_setup(struct dsa_switch *ds) 68895711cd5SPawel Dembicki { 68995711cd5SPawel Dembicki struct vsc73xx *vsc = ds->priv; 690*e3386ec4SPawel Dembicki int i, ret; 69195711cd5SPawel Dembicki 69295711cd5SPawel Dembicki dev_info(vsc->dev, "set up the switch\n"); 69395711cd5SPawel Dembicki 69495711cd5SPawel Dembicki /* Issue RESET */ 69595711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_SYSTEM, 0, VSC73XX_GLORESET, 69695711cd5SPawel Dembicki VSC73XX_GLORESET_MASTER_RESET); 69795711cd5SPawel Dembicki usleep_range(125, 200); 69895711cd5SPawel Dembicki 69995711cd5SPawel Dembicki /* Initialize memory, initialize RAM bank 0..15 except 6 and 7 70095711cd5SPawel Dembicki * This sequence appears in the 70195711cd5SPawel Dembicki * VSC7385 SparX-G5 datasheet section 6.6.1 70295711cd5SPawel Dembicki * VSC7395 SparX-G5e datasheet section 6.6.1 70395711cd5SPawel Dembicki * "initialization sequence". 70495711cd5SPawel Dembicki * No explanation is given to the 0x1010400 magic number. 70595711cd5SPawel Dembicki */ 70695711cd5SPawel Dembicki for (i = 0; i <= 15; i++) { 70795711cd5SPawel Dembicki if (i != 6 && i != 7) { 70895711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MEMINIT, 70995711cd5SPawel Dembicki 2, 71095711cd5SPawel Dembicki 0, 0x1010400 + i); 71195711cd5SPawel Dembicki mdelay(1); 71295711cd5SPawel Dembicki } 71395711cd5SPawel Dembicki } 71495711cd5SPawel Dembicki mdelay(30); 71595711cd5SPawel Dembicki 71695711cd5SPawel Dembicki /* Clear MAC table */ 71795711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, 71895711cd5SPawel Dembicki VSC73XX_MACACCESS, 71995711cd5SPawel Dembicki VSC73XX_MACACCESS_CMD_CLEAR_TABLE); 72095711cd5SPawel Dembicki 7216b783dedSPawel Dembicki /* Set VLAN table to default values */ 72295711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, 72395711cd5SPawel Dembicki VSC73XX_VLANACCESS, 72495711cd5SPawel Dembicki VSC73XX_VLANACCESS_VLAN_TBL_CMD_CLEAR_TABLE); 72595711cd5SPawel Dembicki 72695711cd5SPawel Dembicki msleep(40); 72795711cd5SPawel Dembicki 72895711cd5SPawel Dembicki /* Use 20KiB buffers on all ports on VSC7395 72995711cd5SPawel Dembicki * The VSC7385 has 16KiB buffers and that is the 73095711cd5SPawel Dembicki * default if we don't set this up explicitly. 73195711cd5SPawel Dembicki * Port "31" is "all ports". 73295711cd5SPawel Dembicki */ 73395711cd5SPawel Dembicki if (IS_739X(vsc)) 73495711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 0x1f, 73595711cd5SPawel Dembicki VSC73XX_Q_MISC_CONF, 73695711cd5SPawel Dembicki VSC73XX_Q_MISC_CONF_EXTENT_MEM); 73795711cd5SPawel Dembicki 73895711cd5SPawel Dembicki /* Put all ports into reset until enabled */ 73995711cd5SPawel Dembicki for (i = 0; i < 7; i++) { 74095711cd5SPawel Dembicki if (i == 5) 74195711cd5SPawel Dembicki continue; 74295711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 4, 74395711cd5SPawel Dembicki VSC73XX_MAC_CFG, VSC73XX_MAC_CFG_RESET); 74495711cd5SPawel Dembicki } 74595711cd5SPawel Dembicki 74695711cd5SPawel Dembicki /* MII delay, set both GTX and RX delay to 2 ns */ 74795711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_SYSTEM, 0, VSC73XX_GMIIDELAY, 74895711cd5SPawel Dembicki VSC73XX_GMIIDELAY_GMII0_GTXDELAY_2_0_NS | 74995711cd5SPawel Dembicki VSC73XX_GMIIDELAY_GMII0_RXDELAY_2_0_NS); 7506b783dedSPawel Dembicki /* Ingess VLAN reception mask (table 145) */ 7516b783dedSPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANMASK, 7526b783dedSPawel Dembicki 0xff); 75395711cd5SPawel Dembicki /* IP multicast flood mask (table 144) */ 75495711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_IFLODMSK, 75595711cd5SPawel Dembicki 0xff); 75695711cd5SPawel Dembicki 75795711cd5SPawel Dembicki mdelay(50); 75895711cd5SPawel Dembicki 75995711cd5SPawel Dembicki /* Release reset from the internal PHYs */ 76095711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_SYSTEM, 0, VSC73XX_GLORESET, 76195711cd5SPawel Dembicki VSC73XX_GLORESET_PHY_RESET); 76295711cd5SPawel Dembicki 76395711cd5SPawel Dembicki udelay(4); 76495711cd5SPawel Dembicki 7656b783dedSPawel Dembicki /* Clear VLAN table */ 7666b783dedSPawel Dembicki for (i = 0; i < VLAN_N_VID; i++) 7676b783dedSPawel Dembicki vsc73xx_write_vlan_table_entry(vsc, i, 0); 7686b783dedSPawel Dembicki 7696b783dedSPawel Dembicki INIT_LIST_HEAD(&vsc->vlans); 7706b783dedSPawel Dembicki 771*e3386ec4SPawel Dembicki rtnl_lock(); 772*e3386ec4SPawel Dembicki ret = dsa_tag_8021q_register(ds, htons(ETH_P_8021Q)); 773*e3386ec4SPawel Dembicki rtnl_unlock(); 774*e3386ec4SPawel Dembicki 775*e3386ec4SPawel Dembicki return ret; 776*e3386ec4SPawel Dembicki } 777*e3386ec4SPawel Dembicki 778*e3386ec4SPawel Dembicki static void vsc73xx_teardown(struct dsa_switch *ds) 779*e3386ec4SPawel Dembicki { 780*e3386ec4SPawel Dembicki rtnl_lock(); 781*e3386ec4SPawel Dembicki dsa_tag_8021q_unregister(ds); 782*e3386ec4SPawel Dembicki rtnl_unlock(); 78395711cd5SPawel Dembicki } 78495711cd5SPawel Dembicki 78595711cd5SPawel Dembicki static void vsc73xx_init_port(struct vsc73xx *vsc, int port) 78695711cd5SPawel Dembicki { 78795711cd5SPawel Dembicki u32 val; 78895711cd5SPawel Dembicki 78995711cd5SPawel Dembicki /* MAC configure, first reset the port and then write defaults */ 79095711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 79195711cd5SPawel Dembicki port, 79295711cd5SPawel Dembicki VSC73XX_MAC_CFG, 79395711cd5SPawel Dembicki VSC73XX_MAC_CFG_RESET); 79495711cd5SPawel Dembicki 79595711cd5SPawel Dembicki /* Take up the port in 1Gbit mode by default, this will be 79695711cd5SPawel Dembicki * augmented after auto-negotiation on the PHY-facing 79795711cd5SPawel Dembicki * ports. 79895711cd5SPawel Dembicki */ 79995711cd5SPawel Dembicki if (port == CPU_PORT) 80095711cd5SPawel Dembicki val = VSC73XX_MAC_CFG_1000M_F_RGMII; 80195711cd5SPawel Dembicki else 80295711cd5SPawel Dembicki val = VSC73XX_MAC_CFG_1000M_F_PHY; 80395711cd5SPawel Dembicki 80495711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 80595711cd5SPawel Dembicki port, 80695711cd5SPawel Dembicki VSC73XX_MAC_CFG, 80795711cd5SPawel Dembicki val | 80895711cd5SPawel Dembicki VSC73XX_MAC_CFG_TX_EN | 80995711cd5SPawel Dembicki VSC73XX_MAC_CFG_RX_EN); 81095711cd5SPawel Dembicki 81195711cd5SPawel Dembicki /* Flow control for the CPU port: 81295711cd5SPawel Dembicki * Use a zero delay pause frame when pause condition is left 81395711cd5SPawel Dembicki * Obey pause control frames 81495711cd5SPawel Dembicki */ 81595711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 81695711cd5SPawel Dembicki port, 81795711cd5SPawel Dembicki VSC73XX_FCCONF, 81895711cd5SPawel Dembicki VSC73XX_FCCONF_ZERO_PAUSE_EN | 81995711cd5SPawel Dembicki VSC73XX_FCCONF_FLOW_CTRL_OBEY); 82095711cd5SPawel Dembicki 82195711cd5SPawel Dembicki /* Issue pause control frames on PHY facing ports. 82295711cd5SPawel Dembicki * Allow early initiation of MAC transmission if the amount 82395711cd5SPawel Dembicki * of egress data is below 512 bytes on CPU port. 82495711cd5SPawel Dembicki * FIXME: enable 20KiB buffers? 82595711cd5SPawel Dembicki */ 82695711cd5SPawel Dembicki if (port == CPU_PORT) 82795711cd5SPawel Dembicki val = VSC73XX_Q_MISC_CONF_EARLY_TX_512; 82895711cd5SPawel Dembicki else 82995711cd5SPawel Dembicki val = VSC73XX_Q_MISC_CONF_MAC_PAUSE_MODE; 83095711cd5SPawel Dembicki val |= VSC73XX_Q_MISC_CONF_EXTENT_MEM; 83195711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 83295711cd5SPawel Dembicki port, 83395711cd5SPawel Dembicki VSC73XX_Q_MISC_CONF, 83495711cd5SPawel Dembicki val); 83595711cd5SPawel Dembicki 83695711cd5SPawel Dembicki /* Flow control MAC: a MAC address used in flow control frames */ 83795711cd5SPawel Dembicki val = (vsc->addr[5] << 16) | (vsc->addr[4] << 8) | (vsc->addr[3]); 83895711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 83995711cd5SPawel Dembicki port, 84095711cd5SPawel Dembicki VSC73XX_FCMACHI, 84195711cd5SPawel Dembicki val); 84295711cd5SPawel Dembicki val = (vsc->addr[2] << 16) | (vsc->addr[1] << 8) | (vsc->addr[0]); 84395711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 84495711cd5SPawel Dembicki port, 84595711cd5SPawel Dembicki VSC73XX_FCMACLO, 84695711cd5SPawel Dembicki val); 84795711cd5SPawel Dembicki 84895711cd5SPawel Dembicki /* Tell the categorizer to forward pause frames, not control 84995711cd5SPawel Dembicki * frame. Do not drop anything. 85095711cd5SPawel Dembicki */ 85195711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 85295711cd5SPawel Dembicki port, 85395711cd5SPawel Dembicki VSC73XX_CAT_DROP, 85495711cd5SPawel Dembicki VSC73XX_CAT_DROP_FWD_PAUSE_ENA); 85595711cd5SPawel Dembicki 85695711cd5SPawel Dembicki /* Clear all counters */ 85795711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 85895711cd5SPawel Dembicki port, VSC73XX_C_RX0, 0); 85995711cd5SPawel Dembicki } 86095711cd5SPawel Dembicki 86121fc3416SPawel Dembicki static void vsc73xx_reset_port(struct vsc73xx *vsc, int port, u32 initval) 86295711cd5SPawel Dembicki { 863eb7e33d0SPawel Dembicki int ret, err; 86421fc3416SPawel Dembicki u32 val; 86595711cd5SPawel Dembicki 86695711cd5SPawel Dembicki /* Disable RX on this port */ 86795711cd5SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port, 86895711cd5SPawel Dembicki VSC73XX_MAC_CFG, 86995711cd5SPawel Dembicki VSC73XX_MAC_CFG_RX_EN, 0); 87095711cd5SPawel Dembicki 87195711cd5SPawel Dembicki /* Discard packets */ 87295711cd5SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, 0, 87395711cd5SPawel Dembicki VSC73XX_ARBDISC, BIT(port), BIT(port)); 87495711cd5SPawel Dembicki 87595711cd5SPawel Dembicki /* Wait until queue is empty */ 876eb7e33d0SPawel Dembicki ret = read_poll_timeout(vsc73xx_read, err, 877eb7e33d0SPawel Dembicki err < 0 || (val & BIT(port)), 878eb7e33d0SPawel Dembicki VSC73XX_POLL_SLEEP_US, 879eb7e33d0SPawel Dembicki VSC73XX_POLL_TIMEOUT_US, false, 880eb7e33d0SPawel Dembicki vsc, VSC73XX_BLOCK_ARBITER, 0, 88195711cd5SPawel Dembicki VSC73XX_ARBEMPTY, &val); 882eb7e33d0SPawel Dembicki if (ret) 88395711cd5SPawel Dembicki dev_err(vsc->dev, 88495711cd5SPawel Dembicki "timeout waiting for block arbiter\n"); 885eb7e33d0SPawel Dembicki else if (err < 0) 886eb7e33d0SPawel Dembicki dev_err(vsc->dev, "error reading arbiter\n"); 88795711cd5SPawel Dembicki 88895711cd5SPawel Dembicki /* Put this port into reset */ 88995711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, VSC73XX_MAC_CFG, 89021fc3416SPawel Dembicki VSC73XX_MAC_CFG_RESET | initval); 89121fc3416SPawel Dembicki } 89295711cd5SPawel Dembicki 89321fc3416SPawel Dembicki static void vsc73xx_mac_config(struct phylink_config *config, unsigned int mode, 89421fc3416SPawel Dembicki const struct phylink_link_state *state) 89521fc3416SPawel Dembicki { 89621fc3416SPawel Dembicki struct dsa_port *dp = dsa_phylink_to_port(config); 89721fc3416SPawel Dembicki struct vsc73xx *vsc = dp->ds->priv; 89821fc3416SPawel Dembicki int port = dp->index; 89921fc3416SPawel Dembicki 90021fc3416SPawel Dembicki /* Special handling of the CPU-facing port */ 90121fc3416SPawel Dembicki if (port == CPU_PORT) { 90221fc3416SPawel Dembicki /* Other ports are already initialized but not this one */ 90321fc3416SPawel Dembicki vsc73xx_init_port(vsc, CPU_PORT); 90421fc3416SPawel Dembicki /* Select the external port for this interface (EXT_PORT) 90521fc3416SPawel Dembicki * Enable the GMII GTX external clock 90621fc3416SPawel Dembicki * Use double data rate (DDR mode) 90721fc3416SPawel Dembicki */ 90821fc3416SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 90921fc3416SPawel Dembicki CPU_PORT, 91021fc3416SPawel Dembicki VSC73XX_ADVPORTM, 91121fc3416SPawel Dembicki VSC73XX_ADVPORTM_EXT_PORT | 91221fc3416SPawel Dembicki VSC73XX_ADVPORTM_ENA_GTX | 91321fc3416SPawel Dembicki VSC73XX_ADVPORTM_DDR_MODE); 91421fc3416SPawel Dembicki } 91521fc3416SPawel Dembicki } 91621fc3416SPawel Dembicki 91721fc3416SPawel Dembicki static void vsc73xx_mac_link_down(struct phylink_config *config, 91821fc3416SPawel Dembicki unsigned int mode, phy_interface_t interface) 91921fc3416SPawel Dembicki { 92021fc3416SPawel Dembicki struct dsa_port *dp = dsa_phylink_to_port(config); 92121fc3416SPawel Dembicki struct vsc73xx *vsc = dp->ds->priv; 92221fc3416SPawel Dembicki int port = dp->index; 92321fc3416SPawel Dembicki 92421fc3416SPawel Dembicki /* This routine is described in the datasheet (below ARBDISC register 92521fc3416SPawel Dembicki * description) 92621fc3416SPawel Dembicki */ 92721fc3416SPawel Dembicki vsc73xx_reset_port(vsc, port, 0); 92895711cd5SPawel Dembicki 92995711cd5SPawel Dembicki /* Allow backward dropping of frames from this port */ 93095711cd5SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, 0, 93195711cd5SPawel Dembicki VSC73XX_SBACKWDROP, BIT(port), BIT(port)); 93295711cd5SPawel Dembicki } 93395711cd5SPawel Dembicki 93421fc3416SPawel Dembicki static void vsc73xx_mac_link_up(struct phylink_config *config, 93521fc3416SPawel Dembicki struct phy_device *phy, unsigned int mode, 93621fc3416SPawel Dembicki phy_interface_t interface, int speed, 93721fc3416SPawel Dembicki int duplex, bool tx_pause, bool rx_pause) 93821fc3416SPawel Dembicki { 93921fc3416SPawel Dembicki struct dsa_port *dp = dsa_phylink_to_port(config); 94021fc3416SPawel Dembicki struct vsc73xx *vsc = dp->ds->priv; 94121fc3416SPawel Dembicki int port = dp->index; 94221fc3416SPawel Dembicki u32 val; 94321fc3416SPawel Dembicki u8 seed; 94495711cd5SPawel Dembicki 94521fc3416SPawel Dembicki if (speed == SPEED_1000) 94621fc3416SPawel Dembicki val = VSC73XX_MAC_CFG_GIGA_MODE | VSC73XX_MAC_CFG_TX_IPG_1000M; 94795711cd5SPawel Dembicki else 94821fc3416SPawel Dembicki val = VSC73XX_MAC_CFG_TX_IPG_100_10M; 94995711cd5SPawel Dembicki 95012af94b2SPawel Dembicki if (phy_interface_mode_is_rgmii(interface)) 95121fc3416SPawel Dembicki val |= VSC73XX_MAC_CFG_CLK_SEL_1000M; 95221fc3416SPawel Dembicki else 95321fc3416SPawel Dembicki val |= VSC73XX_MAC_CFG_CLK_SEL_EXT; 95421fc3416SPawel Dembicki 95521fc3416SPawel Dembicki if (duplex == DUPLEX_FULL) 95621fc3416SPawel Dembicki val |= VSC73XX_MAC_CFG_FDX; 95721fc3416SPawel Dembicki 95821fc3416SPawel Dembicki /* This routine is described in the datasheet (below ARBDISC register 95921fc3416SPawel Dembicki * description) 96021fc3416SPawel Dembicki */ 96121fc3416SPawel Dembicki vsc73xx_reset_port(vsc, port, val); 96221fc3416SPawel Dembicki 96321fc3416SPawel Dembicki /* Seed the port randomness with randomness */ 96421fc3416SPawel Dembicki get_random_bytes(&seed, 1); 96521fc3416SPawel Dembicki val |= seed << VSC73XX_MAC_CFG_SEED_OFFSET; 96621fc3416SPawel Dembicki val |= VSC73XX_MAC_CFG_SEED_LOAD; 96721fc3416SPawel Dembicki val |= VSC73XX_MAC_CFG_WEXC_DIS; 9686b783dedSPawel Dembicki 9696b783dedSPawel Dembicki /* Those bits are responsible for MTU only. Kernel takes care about MTU, 9706b783dedSPawel Dembicki * let's enable +8 bytes frame length unconditionally. 9716b783dedSPawel Dembicki */ 9726b783dedSPawel Dembicki val |= VSC73XX_MAC_CFG_VLAN_AWR | VSC73XX_MAC_CFG_VLAN_DBLAWR; 9736b783dedSPawel Dembicki 97421fc3416SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, VSC73XX_MAC_CFG, val); 97521fc3416SPawel Dembicki 97621fc3416SPawel Dembicki /* Flow control for the PHY facing ports: 97721fc3416SPawel Dembicki * Use a zero delay pause frame when pause condition is left 97821fc3416SPawel Dembicki * Obey pause control frames 97921fc3416SPawel Dembicki * When generating pause frames, use 0xff as pause value 98021fc3416SPawel Dembicki */ 98121fc3416SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, VSC73XX_FCCONF, 98221fc3416SPawel Dembicki VSC73XX_FCCONF_ZERO_PAUSE_EN | 98321fc3416SPawel Dembicki VSC73XX_FCCONF_FLOW_CTRL_OBEY | 98421fc3416SPawel Dembicki 0xff); 98521fc3416SPawel Dembicki 98621fc3416SPawel Dembicki /* Accept packets again */ 98721fc3416SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, 0, 98821fc3416SPawel Dembicki VSC73XX_ARBDISC, BIT(port), 0); 98921fc3416SPawel Dembicki 99021fc3416SPawel Dembicki /* Disallow backward dropping of frames from this port */ 99121fc3416SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, 0, 99221fc3416SPawel Dembicki VSC73XX_SBACKWDROP, BIT(port), 0); 99321fc3416SPawel Dembicki 99421fc3416SPawel Dembicki /* Enable TX, RX, deassert reset, stop loading seed */ 99521fc3416SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port, 99621fc3416SPawel Dembicki VSC73XX_MAC_CFG, 99721fc3416SPawel Dembicki VSC73XX_MAC_CFG_RESET | VSC73XX_MAC_CFG_SEED_LOAD | 99821fc3416SPawel Dembicki VSC73XX_MAC_CFG_TX_EN | VSC73XX_MAC_CFG_RX_EN, 99921fc3416SPawel Dembicki VSC73XX_MAC_CFG_TX_EN | VSC73XX_MAC_CFG_RX_EN); 100095711cd5SPawel Dembicki } 100195711cd5SPawel Dembicki 10026b783dedSPawel Dembicki static bool vsc73xx_tag_8021q_active(struct dsa_port *dp) 10036b783dedSPawel Dembicki { 10046b783dedSPawel Dembicki return !dsa_port_is_vlan_filtering(dp); 10056b783dedSPawel Dembicki } 10066b783dedSPawel Dembicki 10076b783dedSPawel Dembicki static struct vsc73xx_bridge_vlan * 10086b783dedSPawel Dembicki vsc73xx_bridge_vlan_find(struct vsc73xx *vsc, u16 vid) 10096b783dedSPawel Dembicki { 10106b783dedSPawel Dembicki struct vsc73xx_bridge_vlan *vlan; 10116b783dedSPawel Dembicki 10126b783dedSPawel Dembicki list_for_each_entry(vlan, &vsc->vlans, list) 10136b783dedSPawel Dembicki if (vlan->vid == vid) 10146b783dedSPawel Dembicki return vlan; 10156b783dedSPawel Dembicki 10166b783dedSPawel Dembicki return NULL; 10176b783dedSPawel Dembicki } 10186b783dedSPawel Dembicki 10196b783dedSPawel Dembicki static void 10206b783dedSPawel Dembicki vsc73xx_bridge_vlan_remove_port(struct vsc73xx_bridge_vlan *vsc73xx_vlan, 10216b783dedSPawel Dembicki int port) 10226b783dedSPawel Dembicki { 10236b783dedSPawel Dembicki vsc73xx_vlan->portmask &= ~BIT(port); 10246b783dedSPawel Dembicki 10256b783dedSPawel Dembicki if (vsc73xx_vlan->portmask) 10266b783dedSPawel Dembicki return; 10276b783dedSPawel Dembicki 10286b783dedSPawel Dembicki list_del(&vsc73xx_vlan->list); 10296b783dedSPawel Dembicki kfree(vsc73xx_vlan); 10306b783dedSPawel Dembicki } 10316b783dedSPawel Dembicki 10326b783dedSPawel Dembicki static void vsc73xx_bridge_vlan_summary(struct vsc73xx *vsc, int port, 10336b783dedSPawel Dembicki struct vsc73xx_vlan_summary *summary, 10346b783dedSPawel Dembicki u16 ignored_vid) 10356b783dedSPawel Dembicki { 10366b783dedSPawel Dembicki size_t num_tagged = 0, num_untagged = 0; 10376b783dedSPawel Dembicki struct vsc73xx_bridge_vlan *vlan; 10386b783dedSPawel Dembicki 10396b783dedSPawel Dembicki list_for_each_entry(vlan, &vsc->vlans, list) { 10406b783dedSPawel Dembicki if (!(vlan->portmask & BIT(port)) || vlan->vid == ignored_vid) 10416b783dedSPawel Dembicki continue; 10426b783dedSPawel Dembicki 10436b783dedSPawel Dembicki if (vlan->untagged & BIT(port)) 10446b783dedSPawel Dembicki num_untagged++; 10456b783dedSPawel Dembicki else 10466b783dedSPawel Dembicki num_tagged++; 10476b783dedSPawel Dembicki } 10486b783dedSPawel Dembicki 10496b783dedSPawel Dembicki summary->num_untagged = num_untagged; 10506b783dedSPawel Dembicki summary->num_tagged = num_tagged; 10516b783dedSPawel Dembicki } 10526b783dedSPawel Dembicki 10536b783dedSPawel Dembicki static u16 vsc73xx_find_first_vlan_untagged(struct vsc73xx *vsc, int port) 10546b783dedSPawel Dembicki { 10556b783dedSPawel Dembicki struct vsc73xx_bridge_vlan *vlan; 10566b783dedSPawel Dembicki 10576b783dedSPawel Dembicki list_for_each_entry(vlan, &vsc->vlans, list) 10586b783dedSPawel Dembicki if ((vlan->portmask & BIT(port)) && 10596b783dedSPawel Dembicki (vlan->untagged & BIT(port))) 10606b783dedSPawel Dembicki return vlan->vid; 10616b783dedSPawel Dembicki 10626b783dedSPawel Dembicki return VLAN_N_VID; 10636b783dedSPawel Dembicki } 10646b783dedSPawel Dembicki 10656b783dedSPawel Dembicki static int vsc73xx_set_vlan_conf(struct vsc73xx *vsc, int port, 10666b783dedSPawel Dembicki enum vsc73xx_port_vlan_conf port_vlan_conf) 10676b783dedSPawel Dembicki { 10686b783dedSPawel Dembicki u32 val = 0; 10696b783dedSPawel Dembicki int ret; 10706b783dedSPawel Dembicki 10716b783dedSPawel Dembicki if (port_vlan_conf == VSC73XX_VLAN_IGNORE) 10726b783dedSPawel Dembicki val = VSC73XX_CAT_VLAN_MISC_VLAN_TCI_IGNORE_ENA | 10736b783dedSPawel Dembicki VSC73XX_CAT_VLAN_MISC_VLAN_KEEP_TAG_ENA; 10746b783dedSPawel Dembicki 10756b783dedSPawel Dembicki ret = vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port, 10766b783dedSPawel Dembicki VSC73XX_CAT_VLAN_MISC, 10776b783dedSPawel Dembicki VSC73XX_CAT_VLAN_MISC_VLAN_TCI_IGNORE_ENA | 10786b783dedSPawel Dembicki VSC73XX_CAT_VLAN_MISC_VLAN_KEEP_TAG_ENA, val); 10796b783dedSPawel Dembicki if (ret) 10806b783dedSPawel Dembicki return ret; 10816b783dedSPawel Dembicki 10826b783dedSPawel Dembicki val = (port_vlan_conf == VSC73XX_VLAN_FILTER) ? 10836b783dedSPawel Dembicki VSC73XX_TXUPDCFG_TX_INSERT_TAG : 0; 10846b783dedSPawel Dembicki 10856b783dedSPawel Dembicki return vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port, 10866b783dedSPawel Dembicki VSC73XX_TXUPDCFG, 10876b783dedSPawel Dembicki VSC73XX_TXUPDCFG_TX_INSERT_TAG, val); 10886b783dedSPawel Dembicki } 10896b783dedSPawel Dembicki 10906b783dedSPawel Dembicki /** 10916b783dedSPawel Dembicki * vsc73xx_vlan_commit_conf - Update VLAN configuration of a port 10926b783dedSPawel Dembicki * @vsc: Switch private data structure 10936b783dedSPawel Dembicki * @port: Port index on which to operate 10946b783dedSPawel Dembicki * 10956b783dedSPawel Dembicki * Update the VLAN behavior of a port to make sure that when it is under 10966b783dedSPawel Dembicki * a VLAN filtering bridge, the port is either filtering with tag 10976b783dedSPawel Dembicki * preservation, or filtering with all VLANs egress-untagged. Otherwise, 10986b783dedSPawel Dembicki * the port ignores VLAN tags from packets and applies the port-based 10996b783dedSPawel Dembicki * VID. 11006b783dedSPawel Dembicki * 11016b783dedSPawel Dembicki * Must be called when changes are made to: 11026b783dedSPawel Dembicki * - the bridge VLAN filtering state of the port 11036b783dedSPawel Dembicki * - the number or attributes of VLANs from the bridge VLAN table, 11046b783dedSPawel Dembicki * while the port is currently VLAN-aware 11056b783dedSPawel Dembicki * 11066b783dedSPawel Dembicki * Return: 0 on success, or negative errno on error. 11076b783dedSPawel Dembicki */ 11086b783dedSPawel Dembicki static int vsc73xx_vlan_commit_conf(struct vsc73xx *vsc, int port) 11096b783dedSPawel Dembicki { 11106b783dedSPawel Dembicki enum vsc73xx_port_vlan_conf port_vlan_conf = VSC73XX_VLAN_IGNORE; 11116b783dedSPawel Dembicki struct dsa_port *dp = dsa_to_port(vsc->ds, port); 11126b783dedSPawel Dembicki 11136b783dedSPawel Dembicki if (port == CPU_PORT) { 11146b783dedSPawel Dembicki port_vlan_conf = VSC73XX_VLAN_FILTER; 11156b783dedSPawel Dembicki } else if (dsa_port_is_vlan_filtering(dp)) { 11166b783dedSPawel Dembicki struct vsc73xx_vlan_summary summary; 11176b783dedSPawel Dembicki 11186b783dedSPawel Dembicki port_vlan_conf = VSC73XX_VLAN_FILTER; 11196b783dedSPawel Dembicki 11206b783dedSPawel Dembicki vsc73xx_bridge_vlan_summary(vsc, port, &summary, VLAN_N_VID); 11216b783dedSPawel Dembicki if (summary.num_tagged == 0) 11226b783dedSPawel Dembicki port_vlan_conf = VSC73XX_VLAN_FILTER_UNTAG_ALL; 11236b783dedSPawel Dembicki } 11246b783dedSPawel Dembicki 11256b783dedSPawel Dembicki return vsc73xx_set_vlan_conf(vsc, port, port_vlan_conf); 11266b783dedSPawel Dembicki } 11276b783dedSPawel Dembicki 11286b783dedSPawel Dembicki static int 11296b783dedSPawel Dembicki vsc73xx_vlan_change_untagged(struct vsc73xx *vsc, int port, u16 vid, bool set) 11306b783dedSPawel Dembicki { 11316b783dedSPawel Dembicki u32 val = 0; 11326b783dedSPawel Dembicki 11336b783dedSPawel Dembicki if (set) 11346b783dedSPawel Dembicki val = VSC73XX_TXUPDCFG_TX_UNTAGGED_VID_ENA | 11356b783dedSPawel Dembicki ((vid << VSC73XX_TXUPDCFG_TX_UNTAGGED_VID_SHIFT) & 11366b783dedSPawel Dembicki VSC73XX_TXUPDCFG_TX_UNTAGGED_VID); 11376b783dedSPawel Dembicki 11386b783dedSPawel Dembicki return vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port, 11396b783dedSPawel Dembicki VSC73XX_TXUPDCFG, 11406b783dedSPawel Dembicki VSC73XX_TXUPDCFG_TX_UNTAGGED_VID_ENA | 11416b783dedSPawel Dembicki VSC73XX_TXUPDCFG_TX_UNTAGGED_VID, val); 11426b783dedSPawel Dembicki } 11436b783dedSPawel Dembicki 11446b783dedSPawel Dembicki /** 11456b783dedSPawel Dembicki * vsc73xx_vlan_commit_untagged - Update native VLAN of a port 11466b783dedSPawel Dembicki * @vsc: Switch private data structure 11476b783dedSPawel Dembicki * @port: Port index on which to operate 11486b783dedSPawel Dembicki * 11496b783dedSPawel Dembicki * Update the native VLAN of a port (the one VLAN which is transmitted 11506b783dedSPawel Dembicki * as egress-tagged on a trunk port) when port is in VLAN filtering mode and 11516b783dedSPawel Dembicki * only one untagged vid is configured. 11526b783dedSPawel Dembicki * In other cases no need to configure it because switch can untag all vlans on 11536b783dedSPawel Dembicki * the port. 11546b783dedSPawel Dembicki * 11556b783dedSPawel Dembicki * Return: 0 on success, or negative errno on error. 11566b783dedSPawel Dembicki */ 11576b783dedSPawel Dembicki static int vsc73xx_vlan_commit_untagged(struct vsc73xx *vsc, int port) 11586b783dedSPawel Dembicki { 11596b783dedSPawel Dembicki struct dsa_port *dp = dsa_to_port(vsc->ds, port); 11606b783dedSPawel Dembicki struct vsc73xx_vlan_summary summary; 11616b783dedSPawel Dembicki u16 vid = 0; 11626b783dedSPawel Dembicki bool valid; 11636b783dedSPawel Dembicki 11646b783dedSPawel Dembicki if (!dsa_port_is_vlan_filtering(dp)) 11656b783dedSPawel Dembicki /* Port is configured to untag all vlans in that case. 11666b783dedSPawel Dembicki * No need to commit untagged config change. 11676b783dedSPawel Dembicki */ 11686b783dedSPawel Dembicki return 0; 11696b783dedSPawel Dembicki 11706b783dedSPawel Dembicki vsc73xx_bridge_vlan_summary(vsc, port, &summary, VLAN_N_VID); 11716b783dedSPawel Dembicki 11726b783dedSPawel Dembicki if (summary.num_untagged > 1) 11736b783dedSPawel Dembicki /* Port must untag all vlans in that case. 11746b783dedSPawel Dembicki * No need to commit untagged config change. 11756b783dedSPawel Dembicki */ 11766b783dedSPawel Dembicki return 0; 11776b783dedSPawel Dembicki 11786b783dedSPawel Dembicki valid = (summary.num_untagged == 1); 11796b783dedSPawel Dembicki if (valid) 11806b783dedSPawel Dembicki vid = vsc73xx_find_first_vlan_untagged(vsc, port); 11816b783dedSPawel Dembicki 11826b783dedSPawel Dembicki return vsc73xx_vlan_change_untagged(vsc, port, vid, valid); 11836b783dedSPawel Dembicki } 11846b783dedSPawel Dembicki 11856b783dedSPawel Dembicki static int 11866b783dedSPawel Dembicki vsc73xx_vlan_change_pvid(struct vsc73xx *vsc, int port, u16 vid, bool set) 11876b783dedSPawel Dembicki { 11886b783dedSPawel Dembicki u32 val = 0; 11896b783dedSPawel Dembicki int ret; 11906b783dedSPawel Dembicki 11916b783dedSPawel Dembicki val = set ? 0 : VSC73XX_CAT_DROP_UNTAGGED_ENA; 11926b783dedSPawel Dembicki 11936b783dedSPawel Dembicki ret = vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port, 11946b783dedSPawel Dembicki VSC73XX_CAT_DROP, 11956b783dedSPawel Dembicki VSC73XX_CAT_DROP_UNTAGGED_ENA, val); 11966b783dedSPawel Dembicki if (!set || ret) 11976b783dedSPawel Dembicki return ret; 11986b783dedSPawel Dembicki 11996b783dedSPawel Dembicki return vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port, 12006b783dedSPawel Dembicki VSC73XX_CAT_PORT_VLAN, 12016b783dedSPawel Dembicki VSC73XX_CAT_PORT_VLAN_VLAN_VID, 12026b783dedSPawel Dembicki vid & VSC73XX_CAT_PORT_VLAN_VLAN_VID); 12036b783dedSPawel Dembicki } 12046b783dedSPawel Dembicki 12056b783dedSPawel Dembicki /** 12066b783dedSPawel Dembicki * vsc73xx_vlan_commit_pvid - Update port-based default VLAN of a port 12076b783dedSPawel Dembicki * @vsc: Switch private data structure 12086b783dedSPawel Dembicki * @port: Port index on which to operate 12096b783dedSPawel Dembicki * 12106b783dedSPawel Dembicki * Update the PVID of a port so that it follows either the bridge PVID 12116b783dedSPawel Dembicki * configuration, when the bridge is currently VLAN-aware, or the PVID 12126b783dedSPawel Dembicki * from tag_8021q, when the port is standalone or under a VLAN-unaware 12136b783dedSPawel Dembicki * bridge. A port with no PVID drops all untagged and VID 0 tagged 12146b783dedSPawel Dembicki * traffic. 12156b783dedSPawel Dembicki * 12166b783dedSPawel Dembicki * Must be called when changes are made to: 12176b783dedSPawel Dembicki * - the bridge VLAN filtering state of the port 12186b783dedSPawel Dembicki * - the number or attributes of VLANs from the bridge VLAN table, 12196b783dedSPawel Dembicki * while the port is currently VLAN-aware 12206b783dedSPawel Dembicki * 12216b783dedSPawel Dembicki * Return: 0 on success, or negative errno on error. 12226b783dedSPawel Dembicki */ 12236b783dedSPawel Dembicki static int vsc73xx_vlan_commit_pvid(struct vsc73xx *vsc, int port) 12246b783dedSPawel Dembicki { 12256b783dedSPawel Dembicki struct vsc73xx_portinfo *portinfo = &vsc->portinfo[port]; 12266b783dedSPawel Dembicki bool valid = portinfo->pvid_tag_8021q_configured; 12276b783dedSPawel Dembicki struct dsa_port *dp = dsa_to_port(vsc->ds, port); 12286b783dedSPawel Dembicki u16 vid = portinfo->pvid_tag_8021q; 12296b783dedSPawel Dembicki 12306b783dedSPawel Dembicki if (dsa_port_is_vlan_filtering(dp)) { 12316b783dedSPawel Dembicki vid = portinfo->pvid_vlan_filtering; 12326b783dedSPawel Dembicki valid = portinfo->pvid_vlan_filtering_configured; 12336b783dedSPawel Dembicki } 12346b783dedSPawel Dembicki 12356b783dedSPawel Dembicki return vsc73xx_vlan_change_pvid(vsc, port, vid, valid); 12366b783dedSPawel Dembicki } 12376b783dedSPawel Dembicki 12386b783dedSPawel Dembicki static int vsc73xx_vlan_commit_settings(struct vsc73xx *vsc, int port) 12396b783dedSPawel Dembicki { 12406b783dedSPawel Dembicki int ret; 12416b783dedSPawel Dembicki 12426b783dedSPawel Dembicki ret = vsc73xx_vlan_commit_untagged(vsc, port); 12436b783dedSPawel Dembicki if (ret) 12446b783dedSPawel Dembicki return ret; 12456b783dedSPawel Dembicki 12466b783dedSPawel Dembicki ret = vsc73xx_vlan_commit_pvid(vsc, port); 12476b783dedSPawel Dembicki if (ret) 12486b783dedSPawel Dembicki return ret; 12496b783dedSPawel Dembicki 12506b783dedSPawel Dembicki return vsc73xx_vlan_commit_conf(vsc, port); 12516b783dedSPawel Dembicki } 12526b783dedSPawel Dembicki 125395711cd5SPawel Dembicki static int vsc73xx_port_enable(struct dsa_switch *ds, int port, 125495711cd5SPawel Dembicki struct phy_device *phy) 125595711cd5SPawel Dembicki { 125695711cd5SPawel Dembicki struct vsc73xx *vsc = ds->priv; 125795711cd5SPawel Dembicki 125895711cd5SPawel Dembicki dev_info(vsc->dev, "enable port %d\n", port); 125995711cd5SPawel Dembicki vsc73xx_init_port(vsc, port); 126095711cd5SPawel Dembicki 12616b783dedSPawel Dembicki return vsc73xx_vlan_commit_settings(vsc, port); 126295711cd5SPawel Dembicki } 126395711cd5SPawel Dembicki 126495711cd5SPawel Dembicki static void vsc73xx_port_disable(struct dsa_switch *ds, int port) 126595711cd5SPawel Dembicki { 126695711cd5SPawel Dembicki struct vsc73xx *vsc = ds->priv; 126795711cd5SPawel Dembicki 126895711cd5SPawel Dembicki /* Just put the port into reset */ 126995711cd5SPawel Dembicki vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, 127095711cd5SPawel Dembicki VSC73XX_MAC_CFG, VSC73XX_MAC_CFG_RESET); 127195711cd5SPawel Dembicki } 127295711cd5SPawel Dembicki 127395711cd5SPawel Dembicki static const struct vsc73xx_counter * 127495711cd5SPawel Dembicki vsc73xx_find_counter(struct vsc73xx *vsc, 127595711cd5SPawel Dembicki u8 counter, 127695711cd5SPawel Dembicki bool tx) 127795711cd5SPawel Dembicki { 127895711cd5SPawel Dembicki const struct vsc73xx_counter *cnts; 127995711cd5SPawel Dembicki int num_cnts; 128095711cd5SPawel Dembicki int i; 128195711cd5SPawel Dembicki 128295711cd5SPawel Dembicki if (tx) { 128395711cd5SPawel Dembicki cnts = vsc73xx_tx_counters; 128495711cd5SPawel Dembicki num_cnts = ARRAY_SIZE(vsc73xx_tx_counters); 128595711cd5SPawel Dembicki } else { 128695711cd5SPawel Dembicki cnts = vsc73xx_rx_counters; 128795711cd5SPawel Dembicki num_cnts = ARRAY_SIZE(vsc73xx_rx_counters); 128895711cd5SPawel Dembicki } 128995711cd5SPawel Dembicki 129095711cd5SPawel Dembicki for (i = 0; i < num_cnts; i++) { 129195711cd5SPawel Dembicki const struct vsc73xx_counter *cnt; 129295711cd5SPawel Dembicki 129395711cd5SPawel Dembicki cnt = &cnts[i]; 129495711cd5SPawel Dembicki if (cnt->counter == counter) 129595711cd5SPawel Dembicki return cnt; 129695711cd5SPawel Dembicki } 129795711cd5SPawel Dembicki 129895711cd5SPawel Dembicki return NULL; 129995711cd5SPawel Dembicki } 130095711cd5SPawel Dembicki 130195711cd5SPawel Dembicki static void vsc73xx_get_strings(struct dsa_switch *ds, int port, u32 stringset, 130295711cd5SPawel Dembicki uint8_t *data) 130395711cd5SPawel Dembicki { 130495711cd5SPawel Dembicki const struct vsc73xx_counter *cnt; 130595711cd5SPawel Dembicki struct vsc73xx *vsc = ds->priv; 130695711cd5SPawel Dembicki u8 indices[6]; 1307e3bbab47SJustin Stitt u8 *buf = data; 1308e3bbab47SJustin Stitt int i; 130995711cd5SPawel Dembicki u32 val; 131095711cd5SPawel Dembicki int ret; 131195711cd5SPawel Dembicki 131295711cd5SPawel Dembicki if (stringset != ETH_SS_STATS) 131395711cd5SPawel Dembicki return; 131495711cd5SPawel Dembicki 131595711cd5SPawel Dembicki ret = vsc73xx_read(vsc, VSC73XX_BLOCK_MAC, port, 131695711cd5SPawel Dembicki VSC73XX_C_CFG, &val); 131795711cd5SPawel Dembicki if (ret) 131895711cd5SPawel Dembicki return; 131995711cd5SPawel Dembicki 132095711cd5SPawel Dembicki indices[0] = (val & 0x1f); /* RX counter 0 */ 132195711cd5SPawel Dembicki indices[1] = ((val >> 5) & 0x1f); /* RX counter 1 */ 132295711cd5SPawel Dembicki indices[2] = ((val >> 10) & 0x1f); /* RX counter 2 */ 132395711cd5SPawel Dembicki indices[3] = ((val >> 16) & 0x1f); /* TX counter 0 */ 132495711cd5SPawel Dembicki indices[4] = ((val >> 21) & 0x1f); /* TX counter 1 */ 132595711cd5SPawel Dembicki indices[5] = ((val >> 26) & 0x1f); /* TX counter 2 */ 132695711cd5SPawel Dembicki 132795711cd5SPawel Dembicki /* The first counters is the RX octets */ 1328e403cfffSjustinstitt@google.com ethtool_puts(&buf, "RxEtherStatsOctets"); 132995711cd5SPawel Dembicki 133095711cd5SPawel Dembicki /* Each port supports recording 3 RX counters and 3 TX counters, 133195711cd5SPawel Dembicki * figure out what counters we use in this set-up and return the 133295711cd5SPawel Dembicki * names of them. The hardware default counters will be number of 133395711cd5SPawel Dembicki * packets on RX/TX, combined broadcast+multicast packets RX/TX and 133495711cd5SPawel Dembicki * total error packets RX/TX. 133595711cd5SPawel Dembicki */ 133695711cd5SPawel Dembicki for (i = 0; i < 3; i++) { 133795711cd5SPawel Dembicki cnt = vsc73xx_find_counter(vsc, indices[i], false); 1338e403cfffSjustinstitt@google.com ethtool_puts(&buf, cnt ? cnt->name : ""); 133995711cd5SPawel Dembicki } 134095711cd5SPawel Dembicki 134195711cd5SPawel Dembicki /* TX stats begins with the number of TX octets */ 1342e403cfffSjustinstitt@google.com ethtool_puts(&buf, "TxEtherStatsOctets"); 134395711cd5SPawel Dembicki 134495711cd5SPawel Dembicki for (i = 3; i < 6; i++) { 134595711cd5SPawel Dembicki cnt = vsc73xx_find_counter(vsc, indices[i], true); 1346e403cfffSjustinstitt@google.com ethtool_puts(&buf, cnt ? cnt->name : ""); 1347e3bbab47SJustin Stitt 134895711cd5SPawel Dembicki } 134995711cd5SPawel Dembicki } 135095711cd5SPawel Dembicki 135195711cd5SPawel Dembicki static int vsc73xx_get_sset_count(struct dsa_switch *ds, int port, int sset) 135295711cd5SPawel Dembicki { 135395711cd5SPawel Dembicki /* We only support SS_STATS */ 135495711cd5SPawel Dembicki if (sset != ETH_SS_STATS) 135595711cd5SPawel Dembicki return 0; 135695711cd5SPawel Dembicki /* RX and TX packets, then 3 RX counters, 3 TX counters */ 135795711cd5SPawel Dembicki return 8; 135895711cd5SPawel Dembicki } 135995711cd5SPawel Dembicki 136095711cd5SPawel Dembicki static void vsc73xx_get_ethtool_stats(struct dsa_switch *ds, int port, 136195711cd5SPawel Dembicki uint64_t *data) 136295711cd5SPawel Dembicki { 136395711cd5SPawel Dembicki struct vsc73xx *vsc = ds->priv; 136495711cd5SPawel Dembicki u8 regs[] = { 136595711cd5SPawel Dembicki VSC73XX_RXOCT, 136695711cd5SPawel Dembicki VSC73XX_C_RX0, 136795711cd5SPawel Dembicki VSC73XX_C_RX1, 136895711cd5SPawel Dembicki VSC73XX_C_RX2, 136995711cd5SPawel Dembicki VSC73XX_TXOCT, 137095711cd5SPawel Dembicki VSC73XX_C_TX0, 137195711cd5SPawel Dembicki VSC73XX_C_TX1, 137295711cd5SPawel Dembicki VSC73XX_C_TX2, 137395711cd5SPawel Dembicki }; 137495711cd5SPawel Dembicki u32 val; 137595711cd5SPawel Dembicki int ret; 137695711cd5SPawel Dembicki int i; 137795711cd5SPawel Dembicki 137895711cd5SPawel Dembicki for (i = 0; i < ARRAY_SIZE(regs); i++) { 137995711cd5SPawel Dembicki ret = vsc73xx_read(vsc, VSC73XX_BLOCK_MAC, port, 138095711cd5SPawel Dembicki regs[i], &val); 138195711cd5SPawel Dembicki if (ret) { 138295711cd5SPawel Dembicki dev_err(vsc->dev, "error reading counter %d\n", i); 138395711cd5SPawel Dembicki return; 138495711cd5SPawel Dembicki } 138595711cd5SPawel Dembicki data[i] = val; 138695711cd5SPawel Dembicki } 138795711cd5SPawel Dembicki } 138895711cd5SPawel Dembicki 1389fb77ffc6SVladimir Oltean static int vsc73xx_change_mtu(struct dsa_switch *ds, int port, int new_mtu) 1390fb77ffc6SVladimir Oltean { 1391fb77ffc6SVladimir Oltean struct vsc73xx *vsc = ds->priv; 1392fb77ffc6SVladimir Oltean 1393fb77ffc6SVladimir Oltean return vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, 13943cf62c81SPawel Dembicki VSC73XX_MAXLEN, new_mtu + ETH_HLEN + ETH_FCS_LEN); 1395fb77ffc6SVladimir Oltean } 1396fb77ffc6SVladimir Oltean 1397fb77ffc6SVladimir Oltean /* According to application not "VSC7398 Jumbo Frames" setting 13983cf62c81SPawel Dembicki * up the frame size to 9.6 KB does not affect the performance on standard 1399fb77ffc6SVladimir Oltean * frames. It is clear from the application note that 1400fb77ffc6SVladimir Oltean * "9.6 kilobytes" == 9600 bytes. 1401fb77ffc6SVladimir Oltean */ 1402fb77ffc6SVladimir Oltean static int vsc73xx_get_max_mtu(struct dsa_switch *ds, int port) 1403fb77ffc6SVladimir Oltean { 14043cf62c81SPawel Dembicki return 9600 - ETH_HLEN - ETH_FCS_LEN; 1405fb77ffc6SVladimir Oltean } 1406fb77ffc6SVladimir Oltean 1407a026809cSRussell King (Oracle) static void vsc73xx_phylink_get_caps(struct dsa_switch *dsa, int port, 1408a026809cSRussell King (Oracle) struct phylink_config *config) 1409a026809cSRussell King (Oracle) { 1410a026809cSRussell King (Oracle) unsigned long *interfaces = config->supported_interfaces; 1411a026809cSRussell King (Oracle) 1412a026809cSRussell King (Oracle) if (port == 5) 1413a026809cSRussell King (Oracle) return; 1414a026809cSRussell King (Oracle) 1415a026809cSRussell King (Oracle) if (port == CPU_PORT) { 1416a026809cSRussell King (Oracle) __set_bit(PHY_INTERFACE_MODE_MII, interfaces); 1417a026809cSRussell King (Oracle) __set_bit(PHY_INTERFACE_MODE_REVMII, interfaces); 1418a026809cSRussell King (Oracle) __set_bit(PHY_INTERFACE_MODE_GMII, interfaces); 1419a026809cSRussell King (Oracle) __set_bit(PHY_INTERFACE_MODE_RGMII, interfaces); 1420a026809cSRussell King (Oracle) } 1421a026809cSRussell King (Oracle) 1422a026809cSRussell King (Oracle) if (port <= 4) { 1423a026809cSRussell King (Oracle) /* Internal PHYs */ 1424a026809cSRussell King (Oracle) __set_bit(PHY_INTERFACE_MODE_INTERNAL, interfaces); 1425a026809cSRussell King (Oracle) /* phylib default */ 1426a026809cSRussell King (Oracle) __set_bit(PHY_INTERFACE_MODE_GMII, interfaces); 1427a026809cSRussell King (Oracle) } 1428a026809cSRussell King (Oracle) 1429a026809cSRussell King (Oracle) config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000; 1430a026809cSRussell King (Oracle) } 1431a026809cSRussell King (Oracle) 14326b783dedSPawel Dembicki static int 14336b783dedSPawel Dembicki vsc73xx_port_vlan_filtering(struct dsa_switch *ds, int port, 14346b783dedSPawel Dembicki bool vlan_filtering, struct netlink_ext_ack *extack) 14356b783dedSPawel Dembicki { 14366b783dedSPawel Dembicki struct vsc73xx *vsc = ds->priv; 14376b783dedSPawel Dembicki 14386b783dedSPawel Dembicki /* The commit to hardware processed below is required because vsc73xx 14396b783dedSPawel Dembicki * is using tag_8021q. When vlan_filtering is disabled, tag_8021q uses 14406b783dedSPawel Dembicki * pvid/untagged vlans for port recognition. The values configured for 14416b783dedSPawel Dembicki * vlans and pvid/untagged states are stored in portinfo structure. 14426b783dedSPawel Dembicki * When vlan_filtering is enabled, we need to restore pvid/untagged from 14436b783dedSPawel Dembicki * portinfo structure. Analogous routine is processed when 14446b783dedSPawel Dembicki * vlan_filtering is disabled, but values used for tag_8021q are 14456b783dedSPawel Dembicki * restored. 14466b783dedSPawel Dembicki */ 14476b783dedSPawel Dembicki 14486b783dedSPawel Dembicki return vsc73xx_vlan_commit_settings(vsc, port); 14496b783dedSPawel Dembicki } 14506b783dedSPawel Dembicki 14516b783dedSPawel Dembicki static int vsc73xx_port_vlan_add(struct dsa_switch *ds, int port, 14526b783dedSPawel Dembicki const struct switchdev_obj_port_vlan *vlan, 14536b783dedSPawel Dembicki struct netlink_ext_ack *extack) 14546b783dedSPawel Dembicki { 14556b783dedSPawel Dembicki bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; 14566b783dedSPawel Dembicki bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; 14576b783dedSPawel Dembicki struct dsa_port *dp = dsa_to_port(ds, port); 14586b783dedSPawel Dembicki struct vsc73xx_bridge_vlan *vsc73xx_vlan; 14596b783dedSPawel Dembicki struct vsc73xx_vlan_summary summary; 14606b783dedSPawel Dembicki struct vsc73xx_portinfo *portinfo; 14616b783dedSPawel Dembicki struct vsc73xx *vsc = ds->priv; 14626b783dedSPawel Dembicki bool commit_to_hardware; 14636b783dedSPawel Dembicki int ret = 0; 14646b783dedSPawel Dembicki 14656b783dedSPawel Dembicki /* Be sure to deny alterations to the configuration done by tag_8021q. 14666b783dedSPawel Dembicki */ 14676b783dedSPawel Dembicki if (vid_is_dsa_8021q(vlan->vid)) { 14686b783dedSPawel Dembicki NL_SET_ERR_MSG_MOD(extack, 14696b783dedSPawel Dembicki "Range 3072-4095 reserved for dsa_8021q operation"); 14706b783dedSPawel Dembicki return -EBUSY; 14716b783dedSPawel Dembicki } 14726b783dedSPawel Dembicki 14736b783dedSPawel Dembicki /* The processed vlan->vid is excluded from the search because the VLAN 14746b783dedSPawel Dembicki * can be re-added with a different set of flags, so it's easiest to 14756b783dedSPawel Dembicki * ignore its old flags from the VLAN database software copy. 14766b783dedSPawel Dembicki */ 14776b783dedSPawel Dembicki vsc73xx_bridge_vlan_summary(vsc, port, &summary, vlan->vid); 14786b783dedSPawel Dembicki 14796b783dedSPawel Dembicki /* VSC73XX allows only three untagged states: none, one or all */ 14806b783dedSPawel Dembicki if ((untagged && summary.num_tagged > 0 && summary.num_untagged > 0) || 14816b783dedSPawel Dembicki (!untagged && summary.num_untagged > 1)) { 14826b783dedSPawel Dembicki NL_SET_ERR_MSG_MOD(extack, 14836b783dedSPawel Dembicki "Port can have only none, one or all untagged vlan"); 14846b783dedSPawel Dembicki return -EBUSY; 14856b783dedSPawel Dembicki } 14866b783dedSPawel Dembicki 14876b783dedSPawel Dembicki vsc73xx_vlan = vsc73xx_bridge_vlan_find(vsc, vlan->vid); 14886b783dedSPawel Dembicki 14896b783dedSPawel Dembicki if (!vsc73xx_vlan) { 14906b783dedSPawel Dembicki vsc73xx_vlan = kzalloc(sizeof(*vsc73xx_vlan), GFP_KERNEL); 14916b783dedSPawel Dembicki if (!vsc73xx_vlan) 14926b783dedSPawel Dembicki return -ENOMEM; 14936b783dedSPawel Dembicki 14946b783dedSPawel Dembicki vsc73xx_vlan->vid = vlan->vid; 14956b783dedSPawel Dembicki 14966b783dedSPawel Dembicki list_add_tail(&vsc73xx_vlan->list, &vsc->vlans); 14976b783dedSPawel Dembicki } 14986b783dedSPawel Dembicki 14996b783dedSPawel Dembicki vsc73xx_vlan->portmask |= BIT(port); 15006b783dedSPawel Dembicki 15016b783dedSPawel Dembicki /* CPU port must be always tagged because source port identification is 15026b783dedSPawel Dembicki * based on tag_8021q. 15036b783dedSPawel Dembicki */ 15046b783dedSPawel Dembicki if (port == CPU_PORT) 15056b783dedSPawel Dembicki goto update_vlan_table; 15066b783dedSPawel Dembicki 15076b783dedSPawel Dembicki if (untagged) 15086b783dedSPawel Dembicki vsc73xx_vlan->untagged |= BIT(port); 15096b783dedSPawel Dembicki else 15106b783dedSPawel Dembicki vsc73xx_vlan->untagged &= ~BIT(port); 15116b783dedSPawel Dembicki 15126b783dedSPawel Dembicki portinfo = &vsc->portinfo[port]; 15136b783dedSPawel Dembicki 15146b783dedSPawel Dembicki if (pvid) { 15156b783dedSPawel Dembicki portinfo->pvid_vlan_filtering_configured = true; 15166b783dedSPawel Dembicki portinfo->pvid_vlan_filtering = vlan->vid; 15176b783dedSPawel Dembicki } else if (portinfo->pvid_vlan_filtering_configured && 15186b783dedSPawel Dembicki portinfo->pvid_vlan_filtering == vlan->vid) { 15196b783dedSPawel Dembicki portinfo->pvid_vlan_filtering_configured = false; 15206b783dedSPawel Dembicki } 15216b783dedSPawel Dembicki 15226b783dedSPawel Dembicki commit_to_hardware = !vsc73xx_tag_8021q_active(dp); 15236b783dedSPawel Dembicki if (commit_to_hardware) { 15246b783dedSPawel Dembicki ret = vsc73xx_vlan_commit_settings(vsc, port); 15256b783dedSPawel Dembicki if (ret) 15266b783dedSPawel Dembicki goto err; 15276b783dedSPawel Dembicki } 15286b783dedSPawel Dembicki 15296b783dedSPawel Dembicki update_vlan_table: 15306b783dedSPawel Dembicki ret = vsc73xx_update_vlan_table(vsc, port, vlan->vid, true); 15316b783dedSPawel Dembicki if (!ret) 15326b783dedSPawel Dembicki return 0; 15336b783dedSPawel Dembicki err: 15346b783dedSPawel Dembicki vsc73xx_bridge_vlan_remove_port(vsc73xx_vlan, port); 15356b783dedSPawel Dembicki return ret; 15366b783dedSPawel Dembicki } 15376b783dedSPawel Dembicki 15386b783dedSPawel Dembicki static int vsc73xx_port_vlan_del(struct dsa_switch *ds, int port, 15396b783dedSPawel Dembicki const struct switchdev_obj_port_vlan *vlan) 15406b783dedSPawel Dembicki { 15416b783dedSPawel Dembicki struct vsc73xx_bridge_vlan *vsc73xx_vlan; 15426b783dedSPawel Dembicki struct vsc73xx_portinfo *portinfo; 15436b783dedSPawel Dembicki struct vsc73xx *vsc = ds->priv; 15446b783dedSPawel Dembicki bool commit_to_hardware; 15456b783dedSPawel Dembicki int ret; 15466b783dedSPawel Dembicki 15476b783dedSPawel Dembicki ret = vsc73xx_update_vlan_table(vsc, port, vlan->vid, false); 15486b783dedSPawel Dembicki if (ret) 15496b783dedSPawel Dembicki return ret; 15506b783dedSPawel Dembicki 15516b783dedSPawel Dembicki portinfo = &vsc->portinfo[port]; 15526b783dedSPawel Dembicki 15536b783dedSPawel Dembicki if (portinfo->pvid_vlan_filtering_configured && 15546b783dedSPawel Dembicki portinfo->pvid_vlan_filtering == vlan->vid) 15556b783dedSPawel Dembicki portinfo->pvid_vlan_filtering_configured = false; 15566b783dedSPawel Dembicki 15576b783dedSPawel Dembicki vsc73xx_vlan = vsc73xx_bridge_vlan_find(vsc, vlan->vid); 15586b783dedSPawel Dembicki 15596b783dedSPawel Dembicki if (vsc73xx_vlan) 15606b783dedSPawel Dembicki vsc73xx_bridge_vlan_remove_port(vsc73xx_vlan, port); 15616b783dedSPawel Dembicki 15626b783dedSPawel Dembicki commit_to_hardware = !vsc73xx_tag_8021q_active(dsa_to_port(ds, port)); 1563*e3386ec4SPawel Dembicki 15646b783dedSPawel Dembicki if (commit_to_hardware) 15656b783dedSPawel Dembicki return vsc73xx_vlan_commit_settings(vsc, port); 15666b783dedSPawel Dembicki 15676b783dedSPawel Dembicki return 0; 15686b783dedSPawel Dembicki } 15696b783dedSPawel Dembicki 1570*e3386ec4SPawel Dembicki static int vsc73xx_tag_8021q_vlan_add(struct dsa_switch *ds, int port, u16 vid, 1571*e3386ec4SPawel Dembicki u16 flags) 1572*e3386ec4SPawel Dembicki { 1573*e3386ec4SPawel Dembicki bool pvid = flags & BRIDGE_VLAN_INFO_PVID; 1574*e3386ec4SPawel Dembicki struct vsc73xx_portinfo *portinfo; 1575*e3386ec4SPawel Dembicki struct vsc73xx *vsc = ds->priv; 1576*e3386ec4SPawel Dembicki bool commit_to_hardware; 1577*e3386ec4SPawel Dembicki int ret; 1578*e3386ec4SPawel Dembicki 1579*e3386ec4SPawel Dembicki portinfo = &vsc->portinfo[port]; 1580*e3386ec4SPawel Dembicki 1581*e3386ec4SPawel Dembicki if (pvid) { 1582*e3386ec4SPawel Dembicki portinfo->pvid_tag_8021q_configured = true; 1583*e3386ec4SPawel Dembicki portinfo->pvid_tag_8021q = vid; 1584*e3386ec4SPawel Dembicki } 1585*e3386ec4SPawel Dembicki 1586*e3386ec4SPawel Dembicki commit_to_hardware = vsc73xx_tag_8021q_active(dsa_to_port(ds, port)); 1587*e3386ec4SPawel Dembicki if (commit_to_hardware) { 1588*e3386ec4SPawel Dembicki ret = vsc73xx_vlan_commit_settings(vsc, port); 1589*e3386ec4SPawel Dembicki if (ret) 1590*e3386ec4SPawel Dembicki return ret; 1591*e3386ec4SPawel Dembicki } 1592*e3386ec4SPawel Dembicki 1593*e3386ec4SPawel Dembicki return vsc73xx_update_vlan_table(vsc, port, vid, true); 1594*e3386ec4SPawel Dembicki } 1595*e3386ec4SPawel Dembicki 1596*e3386ec4SPawel Dembicki static int vsc73xx_tag_8021q_vlan_del(struct dsa_switch *ds, int port, u16 vid) 1597*e3386ec4SPawel Dembicki { 1598*e3386ec4SPawel Dembicki struct vsc73xx_portinfo *portinfo; 1599*e3386ec4SPawel Dembicki struct vsc73xx *vsc = ds->priv; 1600*e3386ec4SPawel Dembicki 1601*e3386ec4SPawel Dembicki portinfo = &vsc->portinfo[port]; 1602*e3386ec4SPawel Dembicki 1603*e3386ec4SPawel Dembicki if (portinfo->pvid_tag_8021q_configured && 1604*e3386ec4SPawel Dembicki portinfo->pvid_tag_8021q == vid) { 1605*e3386ec4SPawel Dembicki struct dsa_port *dp = dsa_to_port(ds, port); 1606*e3386ec4SPawel Dembicki bool commit_to_hardware; 1607*e3386ec4SPawel Dembicki int err; 1608*e3386ec4SPawel Dembicki 1609*e3386ec4SPawel Dembicki portinfo->pvid_tag_8021q_configured = false; 1610*e3386ec4SPawel Dembicki 1611*e3386ec4SPawel Dembicki commit_to_hardware = vsc73xx_tag_8021q_active(dp); 1612*e3386ec4SPawel Dembicki if (commit_to_hardware) { 1613*e3386ec4SPawel Dembicki err = vsc73xx_vlan_commit_settings(vsc, port); 1614*e3386ec4SPawel Dembicki if (err) 1615*e3386ec4SPawel Dembicki return err; 1616*e3386ec4SPawel Dembicki } 1617*e3386ec4SPawel Dembicki } 1618*e3386ec4SPawel Dembicki 1619*e3386ec4SPawel Dembicki return vsc73xx_update_vlan_table(vsc, port, vid, false); 1620*e3386ec4SPawel Dembicki } 1621*e3386ec4SPawel Dembicki 16221e5b23e5SPawel Dembicki static void vsc73xx_refresh_fwd_map(struct dsa_switch *ds, int port, u8 state) 16231e5b23e5SPawel Dembicki { 16241e5b23e5SPawel Dembicki struct dsa_port *other_dp, *dp = dsa_to_port(ds, port); 16251e5b23e5SPawel Dembicki struct vsc73xx *vsc = ds->priv; 16261e5b23e5SPawel Dembicki u16 mask; 16271e5b23e5SPawel Dembicki 16281e5b23e5SPawel Dembicki if (state != BR_STATE_FORWARDING) { 16291e5b23e5SPawel Dembicki /* Ports that aren't in the forwarding state must not 16301e5b23e5SPawel Dembicki * forward packets anywhere. 16311e5b23e5SPawel Dembicki */ 16321e5b23e5SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, 16331e5b23e5SPawel Dembicki VSC73XX_SRCMASKS + port, 16341e5b23e5SPawel Dembicki VSC73XX_SRCMASKS_PORTS_MASK, 0); 16351e5b23e5SPawel Dembicki 16361e5b23e5SPawel Dembicki dsa_switch_for_each_available_port(other_dp, ds) { 16371e5b23e5SPawel Dembicki if (other_dp == dp) 16381e5b23e5SPawel Dembicki continue; 16391e5b23e5SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, 16401e5b23e5SPawel Dembicki VSC73XX_SRCMASKS + other_dp->index, 16411e5b23e5SPawel Dembicki BIT(port), 0); 16421e5b23e5SPawel Dembicki } 16431e5b23e5SPawel Dembicki 16441e5b23e5SPawel Dembicki return; 16451e5b23e5SPawel Dembicki } 16461e5b23e5SPawel Dembicki 16471e5b23e5SPawel Dembicki /* Forwarding ports must forward to the CPU and to other ports 16481e5b23e5SPawel Dembicki * in the same bridge 16491e5b23e5SPawel Dembicki */ 16501e5b23e5SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, 16511e5b23e5SPawel Dembicki VSC73XX_SRCMASKS + CPU_PORT, BIT(port), BIT(port)); 16521e5b23e5SPawel Dembicki 16531e5b23e5SPawel Dembicki mask = BIT(CPU_PORT); 16541e5b23e5SPawel Dembicki 16551e5b23e5SPawel Dembicki dsa_switch_for_each_user_port(other_dp, ds) { 16561e5b23e5SPawel Dembicki int other_port = other_dp->index; 16571e5b23e5SPawel Dembicki 16581e5b23e5SPawel Dembicki if (port == other_port || !dsa_port_bridge_same(dp, other_dp) || 16591e5b23e5SPawel Dembicki other_dp->stp_state != BR_STATE_FORWARDING) 16601e5b23e5SPawel Dembicki continue; 16611e5b23e5SPawel Dembicki 16621e5b23e5SPawel Dembicki mask |= BIT(other_port); 16631e5b23e5SPawel Dembicki 16641e5b23e5SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, 16651e5b23e5SPawel Dembicki VSC73XX_SRCMASKS + other_port, 16661e5b23e5SPawel Dembicki BIT(port), BIT(port)); 16671e5b23e5SPawel Dembicki } 16681e5b23e5SPawel Dembicki 16691e5b23e5SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, 16701e5b23e5SPawel Dembicki VSC73XX_SRCMASKS + port, 16711e5b23e5SPawel Dembicki VSC73XX_SRCMASKS_PORTS_MASK, mask); 16721e5b23e5SPawel Dembicki } 16731e5b23e5SPawel Dembicki 16741e5b23e5SPawel Dembicki /* FIXME: STP frames aren't forwarded at this moment. BPDU frames are 16751e5b23e5SPawel Dembicki * forwarded only from and to PI/SI interface. For more info see chapter 16761e5b23e5SPawel Dembicki * 2.7.1 (CPU Forwarding) in datasheet. 16771e5b23e5SPawel Dembicki * This function is required for tag_8021q operations. 16781e5b23e5SPawel Dembicki */ 16791e5b23e5SPawel Dembicki static void vsc73xx_port_stp_state_set(struct dsa_switch *ds, int port, 16801e5b23e5SPawel Dembicki u8 state) 16811e5b23e5SPawel Dembicki { 16821e5b23e5SPawel Dembicki struct vsc73xx *vsc = ds->priv; 16831e5b23e5SPawel Dembicki u32 val; 16841e5b23e5SPawel Dembicki 16851e5b23e5SPawel Dembicki val = (state == BR_STATE_BLOCKING || state == BR_STATE_DISABLED) ? 16861e5b23e5SPawel Dembicki 0 : BIT(port); 16871e5b23e5SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, 16881e5b23e5SPawel Dembicki VSC73XX_RECVMASK, BIT(port), val); 16891e5b23e5SPawel Dembicki 16901e5b23e5SPawel Dembicki val = (state == BR_STATE_LEARNING || state == BR_STATE_FORWARDING) ? 16911e5b23e5SPawel Dembicki BIT(port) : 0; 16921e5b23e5SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, 16931e5b23e5SPawel Dembicki VSC73XX_LEARNMASK, BIT(port), val); 16941e5b23e5SPawel Dembicki 16951e5b23e5SPawel Dembicki /* CPU Port should always forward packets when user ports are forwarding 16961e5b23e5SPawel Dembicki * so let's configure it from other ports only. 16971e5b23e5SPawel Dembicki */ 16981e5b23e5SPawel Dembicki if (port != CPU_PORT) 16991e5b23e5SPawel Dembicki vsc73xx_refresh_fwd_map(ds, port, state); 17001e5b23e5SPawel Dembicki } 17011e5b23e5SPawel Dembicki 170221fc3416SPawel Dembicki static const struct phylink_mac_ops vsc73xx_phylink_mac_ops = { 170321fc3416SPawel Dembicki .mac_config = vsc73xx_mac_config, 170421fc3416SPawel Dembicki .mac_link_down = vsc73xx_mac_link_down, 170521fc3416SPawel Dembicki .mac_link_up = vsc73xx_mac_link_up, 170621fc3416SPawel Dembicki }; 170721fc3416SPawel Dembicki 170895711cd5SPawel Dembicki static const struct dsa_switch_ops vsc73xx_ds_ops = { 170995711cd5SPawel Dembicki .get_tag_protocol = vsc73xx_get_tag_protocol, 171095711cd5SPawel Dembicki .setup = vsc73xx_setup, 1711*e3386ec4SPawel Dembicki .teardown = vsc73xx_teardown, 171295711cd5SPawel Dembicki .phy_read = vsc73xx_phy_read, 171395711cd5SPawel Dembicki .phy_write = vsc73xx_phy_write, 171495711cd5SPawel Dembicki .get_strings = vsc73xx_get_strings, 171595711cd5SPawel Dembicki .get_ethtool_stats = vsc73xx_get_ethtool_stats, 171695711cd5SPawel Dembicki .get_sset_count = vsc73xx_get_sset_count, 171795711cd5SPawel Dembicki .port_enable = vsc73xx_port_enable, 171895711cd5SPawel Dembicki .port_disable = vsc73xx_port_disable, 1719fb77ffc6SVladimir Oltean .port_change_mtu = vsc73xx_change_mtu, 1720fb77ffc6SVladimir Oltean .port_max_mtu = vsc73xx_get_max_mtu, 17211e5b23e5SPawel Dembicki .port_stp_state_set = vsc73xx_port_stp_state_set, 17226b783dedSPawel Dembicki .port_vlan_filtering = vsc73xx_port_vlan_filtering, 17236b783dedSPawel Dembicki .port_vlan_add = vsc73xx_port_vlan_add, 17246b783dedSPawel Dembicki .port_vlan_del = vsc73xx_port_vlan_del, 1725a026809cSRussell King (Oracle) .phylink_get_caps = vsc73xx_phylink_get_caps, 1726*e3386ec4SPawel Dembicki .tag_8021q_vlan_add = vsc73xx_tag_8021q_vlan_add, 1727*e3386ec4SPawel Dembicki .tag_8021q_vlan_del = vsc73xx_tag_8021q_vlan_del, 172895711cd5SPawel Dembicki }; 172995711cd5SPawel Dembicki 173095711cd5SPawel Dembicki static int vsc73xx_gpio_get(struct gpio_chip *chip, unsigned int offset) 173195711cd5SPawel Dembicki { 173295711cd5SPawel Dembicki struct vsc73xx *vsc = gpiochip_get_data(chip); 173395711cd5SPawel Dembicki u32 val; 173495711cd5SPawel Dembicki int ret; 173595711cd5SPawel Dembicki 173695711cd5SPawel Dembicki ret = vsc73xx_read(vsc, VSC73XX_BLOCK_SYSTEM, 0, 173795711cd5SPawel Dembicki VSC73XX_GPIO, &val); 173895711cd5SPawel Dembicki if (ret) 173995711cd5SPawel Dembicki return ret; 174095711cd5SPawel Dembicki 174195711cd5SPawel Dembicki return !!(val & BIT(offset)); 174295711cd5SPawel Dembicki } 174395711cd5SPawel Dembicki 174495711cd5SPawel Dembicki static void vsc73xx_gpio_set(struct gpio_chip *chip, unsigned int offset, 174595711cd5SPawel Dembicki int val) 174695711cd5SPawel Dembicki { 174795711cd5SPawel Dembicki struct vsc73xx *vsc = gpiochip_get_data(chip); 174895711cd5SPawel Dembicki u32 tmp = val ? BIT(offset) : 0; 174995711cd5SPawel Dembicki 175095711cd5SPawel Dembicki vsc73xx_update_bits(vsc, VSC73XX_BLOCK_SYSTEM, 0, 175195711cd5SPawel Dembicki VSC73XX_GPIO, BIT(offset), tmp); 175295711cd5SPawel Dembicki } 175395711cd5SPawel Dembicki 175495711cd5SPawel Dembicki static int vsc73xx_gpio_direction_output(struct gpio_chip *chip, 175595711cd5SPawel Dembicki unsigned int offset, int val) 175695711cd5SPawel Dembicki { 175795711cd5SPawel Dembicki struct vsc73xx *vsc = gpiochip_get_data(chip); 175895711cd5SPawel Dembicki u32 tmp = val ? BIT(offset) : 0; 175995711cd5SPawel Dembicki 176095711cd5SPawel Dembicki return vsc73xx_update_bits(vsc, VSC73XX_BLOCK_SYSTEM, 0, 176195711cd5SPawel Dembicki VSC73XX_GPIO, BIT(offset + 4) | BIT(offset), 176295711cd5SPawel Dembicki BIT(offset + 4) | tmp); 176395711cd5SPawel Dembicki } 176495711cd5SPawel Dembicki 176595711cd5SPawel Dembicki static int vsc73xx_gpio_direction_input(struct gpio_chip *chip, 176695711cd5SPawel Dembicki unsigned int offset) 176795711cd5SPawel Dembicki { 176895711cd5SPawel Dembicki struct vsc73xx *vsc = gpiochip_get_data(chip); 176995711cd5SPawel Dembicki 177095711cd5SPawel Dembicki return vsc73xx_update_bits(vsc, VSC73XX_BLOCK_SYSTEM, 0, 177195711cd5SPawel Dembicki VSC73XX_GPIO, BIT(offset + 4), 177295711cd5SPawel Dembicki 0); 177395711cd5SPawel Dembicki } 177495711cd5SPawel Dembicki 177595711cd5SPawel Dembicki static int vsc73xx_gpio_get_direction(struct gpio_chip *chip, 177695711cd5SPawel Dembicki unsigned int offset) 177795711cd5SPawel Dembicki { 177895711cd5SPawel Dembicki struct vsc73xx *vsc = gpiochip_get_data(chip); 177995711cd5SPawel Dembicki u32 val; 178095711cd5SPawel Dembicki int ret; 178195711cd5SPawel Dembicki 178295711cd5SPawel Dembicki ret = vsc73xx_read(vsc, VSC73XX_BLOCK_SYSTEM, 0, 178395711cd5SPawel Dembicki VSC73XX_GPIO, &val); 178495711cd5SPawel Dembicki if (ret) 178595711cd5SPawel Dembicki return ret; 178695711cd5SPawel Dembicki 178795711cd5SPawel Dembicki return !(val & BIT(offset + 4)); 178895711cd5SPawel Dembicki } 178995711cd5SPawel Dembicki 179095711cd5SPawel Dembicki static int vsc73xx_gpio_probe(struct vsc73xx *vsc) 179195711cd5SPawel Dembicki { 179295711cd5SPawel Dembicki int ret; 179395711cd5SPawel Dembicki 179495711cd5SPawel Dembicki vsc->gc.label = devm_kasprintf(vsc->dev, GFP_KERNEL, "VSC%04x", 179595711cd5SPawel Dembicki vsc->chipid); 1796776dac5aSKunwu Chan if (!vsc->gc.label) 1797776dac5aSKunwu Chan return -ENOMEM; 179895711cd5SPawel Dembicki vsc->gc.ngpio = 4; 179995711cd5SPawel Dembicki vsc->gc.owner = THIS_MODULE; 180095711cd5SPawel Dembicki vsc->gc.parent = vsc->dev; 180195711cd5SPawel Dembicki vsc->gc.base = -1; 180295711cd5SPawel Dembicki vsc->gc.get = vsc73xx_gpio_get; 180395711cd5SPawel Dembicki vsc->gc.set = vsc73xx_gpio_set; 180495711cd5SPawel Dembicki vsc->gc.direction_input = vsc73xx_gpio_direction_input; 180595711cd5SPawel Dembicki vsc->gc.direction_output = vsc73xx_gpio_direction_output; 180695711cd5SPawel Dembicki vsc->gc.get_direction = vsc73xx_gpio_get_direction; 180795711cd5SPawel Dembicki vsc->gc.can_sleep = true; 180895711cd5SPawel Dembicki ret = devm_gpiochip_add_data(vsc->dev, &vsc->gc, vsc); 180995711cd5SPawel Dembicki if (ret) { 181095711cd5SPawel Dembicki dev_err(vsc->dev, "unable to register GPIO chip\n"); 181195711cd5SPawel Dembicki return ret; 181295711cd5SPawel Dembicki } 181395711cd5SPawel Dembicki return 0; 181495711cd5SPawel Dembicki } 181595711cd5SPawel Dembicki 181695711cd5SPawel Dembicki int vsc73xx_probe(struct vsc73xx *vsc) 181795711cd5SPawel Dembicki { 181895711cd5SPawel Dembicki struct device *dev = vsc->dev; 181995711cd5SPawel Dembicki int ret; 182095711cd5SPawel Dembicki 182195711cd5SPawel Dembicki /* Release reset, if any */ 182295711cd5SPawel Dembicki vsc->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); 182395711cd5SPawel Dembicki if (IS_ERR(vsc->reset)) { 182495711cd5SPawel Dembicki dev_err(dev, "failed to get RESET GPIO\n"); 182595711cd5SPawel Dembicki return PTR_ERR(vsc->reset); 182695711cd5SPawel Dembicki } 182795711cd5SPawel Dembicki if (vsc->reset) 182895711cd5SPawel Dembicki /* Wait 20ms according to datasheet table 245 */ 182995711cd5SPawel Dembicki msleep(20); 183095711cd5SPawel Dembicki 183195711cd5SPawel Dembicki ret = vsc73xx_detect(vsc); 18321da39ff0SPawel Dembicki if (ret == -EAGAIN) { 18331da39ff0SPawel Dembicki dev_err(vsc->dev, 18341da39ff0SPawel Dembicki "Chip seems to be out of control. Assert reset and try again.\n"); 18351da39ff0SPawel Dembicki gpiod_set_value_cansleep(vsc->reset, 1); 18361da39ff0SPawel Dembicki /* Reset pulse should be 20ns minimum, according to datasheet 18371da39ff0SPawel Dembicki * table 245, so 10us should be fine 18381da39ff0SPawel Dembicki */ 18391da39ff0SPawel Dembicki usleep_range(10, 100); 18401da39ff0SPawel Dembicki gpiod_set_value_cansleep(vsc->reset, 0); 18411da39ff0SPawel Dembicki /* Wait 20ms according to datasheet table 245 */ 18421da39ff0SPawel Dembicki msleep(20); 18431da39ff0SPawel Dembicki ret = vsc73xx_detect(vsc); 18441da39ff0SPawel Dembicki } 184595711cd5SPawel Dembicki if (ret) { 184695711cd5SPawel Dembicki dev_err(dev, "no chip found (%d)\n", ret); 184795711cd5SPawel Dembicki return -ENODEV; 184895711cd5SPawel Dembicki } 184995711cd5SPawel Dembicki 185095711cd5SPawel Dembicki eth_random_addr(vsc->addr); 185195711cd5SPawel Dembicki dev_info(vsc->dev, 185295711cd5SPawel Dembicki "MAC for control frames: %02X:%02X:%02X:%02X:%02X:%02X\n", 185395711cd5SPawel Dembicki vsc->addr[0], vsc->addr[1], vsc->addr[2], 185495711cd5SPawel Dembicki vsc->addr[3], vsc->addr[4], vsc->addr[5]); 185595711cd5SPawel Dembicki 18567e99e347SVivien Didelot vsc->ds = devm_kzalloc(dev, sizeof(*vsc->ds), GFP_KERNEL); 185795711cd5SPawel Dembicki if (!vsc->ds) 185895711cd5SPawel Dembicki return -ENOMEM; 18597e99e347SVivien Didelot 18607e99e347SVivien Didelot vsc->ds->dev = dev; 18616cc5280aSPawel Dembicki vsc->ds->num_ports = VSC73XX_MAX_NUM_PORTS; 186295711cd5SPawel Dembicki vsc->ds->priv = vsc; 186395711cd5SPawel Dembicki 186495711cd5SPawel Dembicki vsc->ds->ops = &vsc73xx_ds_ops; 186521fc3416SPawel Dembicki vsc->ds->phylink_mac_ops = &vsc73xx_phylink_mac_ops; 186695711cd5SPawel Dembicki ret = dsa_register_switch(vsc->ds); 186795711cd5SPawel Dembicki if (ret) { 186895711cd5SPawel Dembicki dev_err(dev, "unable to register switch (%d)\n", ret); 186995711cd5SPawel Dembicki return ret; 187095711cd5SPawel Dembicki } 187195711cd5SPawel Dembicki 187295711cd5SPawel Dembicki ret = vsc73xx_gpio_probe(vsc); 187395711cd5SPawel Dembicki if (ret) { 187495711cd5SPawel Dembicki dsa_unregister_switch(vsc->ds); 187595711cd5SPawel Dembicki return ret; 187695711cd5SPawel Dembicki } 187795711cd5SPawel Dembicki 187895711cd5SPawel Dembicki return 0; 187995711cd5SPawel Dembicki } 188095711cd5SPawel Dembicki EXPORT_SYMBOL(vsc73xx_probe); 188195711cd5SPawel Dembicki 1882e99fa423SUwe Kleine-König void vsc73xx_remove(struct vsc73xx *vsc) 188395711cd5SPawel Dembicki { 188495711cd5SPawel Dembicki dsa_unregister_switch(vsc->ds); 188595711cd5SPawel Dembicki gpiod_set_value(vsc->reset, 1); 188695711cd5SPawel Dembicki } 188795711cd5SPawel Dembicki EXPORT_SYMBOL(vsc73xx_remove); 188895711cd5SPawel Dembicki 18890650bf52SVladimir Oltean void vsc73xx_shutdown(struct vsc73xx *vsc) 18900650bf52SVladimir Oltean { 18910650bf52SVladimir Oltean dsa_switch_shutdown(vsc->ds); 18920650bf52SVladimir Oltean } 18930650bf52SVladimir Oltean EXPORT_SYMBOL(vsc73xx_shutdown); 18940650bf52SVladimir Oltean 189595711cd5SPawel Dembicki MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); 189695711cd5SPawel Dembicki MODULE_DESCRIPTION("Vitesse VSC7385/7388/7395/7398 driver"); 189795711cd5SPawel Dembicki MODULE_LICENSE("GPL v2"); 1898