xref: /linux/drivers/net/dsa/vitesse-vsc73xx-core.c (revision 8d5be2c4f4477915fee079572665198e70246b69)
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 
43*8d5be2c4SPawel Dembicki /* MII Block subblock */
44*8d5be2c4SPawel Dembicki #define VSC73XX_BLOCK_MII_INTERNAL     0x0 /* Internal MDIO subblock */
45*8d5be2c4SPawel Dembicki 
4695711cd5SPawel Dembicki #define CPU_PORT	6 /* CPU port */
4795711cd5SPawel Dembicki 
4895711cd5SPawel Dembicki /* MAC Block registers */
4995711cd5SPawel Dembicki #define VSC73XX_MAC_CFG		0x00
5095711cd5SPawel Dembicki #define VSC73XX_MACHDXGAP	0x02
5195711cd5SPawel Dembicki #define VSC73XX_FCCONF		0x04
5295711cd5SPawel Dembicki #define VSC73XX_FCMACHI		0x08
5395711cd5SPawel Dembicki #define VSC73XX_FCMACLO		0x0c
5495711cd5SPawel Dembicki #define VSC73XX_MAXLEN		0x10
5595711cd5SPawel Dembicki #define VSC73XX_ADVPORTM	0x19
5695711cd5SPawel Dembicki #define VSC73XX_TXUPDCFG	0x24
5795711cd5SPawel Dembicki #define VSC73XX_TXQ_SELECT_CFG	0x28
5895711cd5SPawel Dembicki #define VSC73XX_RXOCT		0x50
5995711cd5SPawel Dembicki #define VSC73XX_TXOCT		0x51
6095711cd5SPawel Dembicki #define VSC73XX_C_RX0		0x52
6195711cd5SPawel Dembicki #define VSC73XX_C_RX1		0x53
6295711cd5SPawel Dembicki #define VSC73XX_C_RX2		0x54
6395711cd5SPawel Dembicki #define VSC73XX_C_TX0		0x55
6495711cd5SPawel Dembicki #define VSC73XX_C_TX1		0x56
6595711cd5SPawel Dembicki #define VSC73XX_C_TX2		0x57
6695711cd5SPawel Dembicki #define VSC73XX_C_CFG		0x58
6795711cd5SPawel Dembicki #define VSC73XX_CAT_DROP	0x6e
6895711cd5SPawel Dembicki #define VSC73XX_CAT_PR_MISC_L2	0x6f
6995711cd5SPawel Dembicki #define VSC73XX_CAT_PR_USR_PRIO	0x75
706b783dedSPawel Dembicki #define VSC73XX_CAT_VLAN_MISC	0x79
716b783dedSPawel Dembicki #define VSC73XX_CAT_PORT_VLAN	0x7a
7295711cd5SPawel Dembicki #define VSC73XX_Q_MISC_CONF	0xdf
7395711cd5SPawel Dembicki 
7495711cd5SPawel Dembicki /* MAC_CFG register bits */
7595711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_WEXC_DIS	BIT(31)
7695711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_PORT_RST	BIT(29)
7795711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_TX_EN		BIT(28)
7895711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_SEED_LOAD	BIT(27)
7995711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_SEED_MASK	GENMASK(26, 19)
8095711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_SEED_OFFSET	19
8195711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_FDX		BIT(18)
8295711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_GIGA_MODE	BIT(17)
8395711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_RX_EN		BIT(16)
8495711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_VLAN_DBLAWR	BIT(15)
8595711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_VLAN_AWR	BIT(14)
8695711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_100_BASE_T	BIT(13) /* Not in manual */
8795711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_TX_IPG_MASK	GENMASK(10, 6)
8895711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_TX_IPG_OFFSET	6
8995711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_TX_IPG_1000M	(6 << VSC73XX_MAC_CFG_TX_IPG_OFFSET)
9095711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_TX_IPG_100_10M	(17 << VSC73XX_MAC_CFG_TX_IPG_OFFSET)
9195711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_MAC_RX_RST	BIT(5)
9295711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_MAC_TX_RST	BIT(4)
9395711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_CLK_SEL_MASK	GENMASK(2, 0)
9495711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_CLK_SEL_OFFSET	0
9595711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_CLK_SEL_1000M	1
9695711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_CLK_SEL_100M	2
9795711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_CLK_SEL_10M	3
9895711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_CLK_SEL_EXT	4
9995711cd5SPawel Dembicki 
10095711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_1000M_F_PHY	(VSC73XX_MAC_CFG_FDX | \
10195711cd5SPawel Dembicki 					 VSC73XX_MAC_CFG_GIGA_MODE | \
10295711cd5SPawel Dembicki 					 VSC73XX_MAC_CFG_TX_IPG_1000M | \
10395711cd5SPawel Dembicki 					 VSC73XX_MAC_CFG_CLK_SEL_EXT)
10495711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_100_10M_F_PHY	(VSC73XX_MAC_CFG_FDX | \
10595711cd5SPawel Dembicki 					 VSC73XX_MAC_CFG_TX_IPG_100_10M | \
10695711cd5SPawel Dembicki 					 VSC73XX_MAC_CFG_CLK_SEL_EXT)
10795711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_100_10M_H_PHY	(VSC73XX_MAC_CFG_TX_IPG_100_10M | \
10895711cd5SPawel Dembicki 					 VSC73XX_MAC_CFG_CLK_SEL_EXT)
10995711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_1000M_F_RGMII	(VSC73XX_MAC_CFG_FDX | \
11095711cd5SPawel Dembicki 					 VSC73XX_MAC_CFG_GIGA_MODE | \
11195711cd5SPawel Dembicki 					 VSC73XX_MAC_CFG_TX_IPG_1000M | \
11295711cd5SPawel Dembicki 					 VSC73XX_MAC_CFG_CLK_SEL_1000M)
11395711cd5SPawel Dembicki #define VSC73XX_MAC_CFG_RESET		(VSC73XX_MAC_CFG_PORT_RST | \
11495711cd5SPawel Dembicki 					 VSC73XX_MAC_CFG_MAC_RX_RST | \
11595711cd5SPawel Dembicki 					 VSC73XX_MAC_CFG_MAC_TX_RST)
11695711cd5SPawel Dembicki 
11795711cd5SPawel Dembicki /* Flow control register bits */
11895711cd5SPawel Dembicki #define VSC73XX_FCCONF_ZERO_PAUSE_EN	BIT(17)
11995711cd5SPawel Dembicki #define VSC73XX_FCCONF_FLOW_CTRL_OBEY	BIT(16)
12095711cd5SPawel Dembicki #define VSC73XX_FCCONF_PAUSE_VAL_MASK	GENMASK(15, 0)
12195711cd5SPawel Dembicki 
12295711cd5SPawel Dembicki /* ADVPORTM advanced port setup register bits */
12395711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_IFG_PPM	BIT(7)
12495711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_EXC_COL_CONT	BIT(6)
12595711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_EXT_PORT	BIT(5)
12695711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_INV_GTX	BIT(4)
12795711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_ENA_GTX	BIT(3)
12895711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_DDR_MODE	BIT(2)
12995711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_IO_LOOPBACK	BIT(1)
13095711cd5SPawel Dembicki #define VSC73XX_ADVPORTM_HOST_LOOPBACK	BIT(0)
13195711cd5SPawel Dembicki 
1326b783dedSPawel Dembicki /*  TXUPDCFG transmit modify setup bits */
1336b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_DSCP_REWR_MODE	GENMASK(20, 19)
1346b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_DSCP_REWR_ENA	BIT(18)
1356b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_TX_INT_TO_USRPRIO_ENA	BIT(17)
1366b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_TX_UNTAGGED_VID	GENMASK(15, 4)
1376b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_TX_UNTAGGED_VID_ENA	BIT(3)
1386b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_TX_UPDATE_CRC_CPU_ENA	BIT(1)
1396b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_TX_INSERT_TAG	BIT(0)
1406b783dedSPawel Dembicki 
1416b783dedSPawel Dembicki #define VSC73XX_TXUPDCFG_TX_UNTAGGED_VID_SHIFT	4
1426b783dedSPawel Dembicki 
14395711cd5SPawel Dembicki /* CAT_DROP categorizer frame dropping register bits */
14495711cd5SPawel Dembicki #define VSC73XX_CAT_DROP_DROP_MC_SMAC_ENA	BIT(6)
14595711cd5SPawel Dembicki #define VSC73XX_CAT_DROP_FWD_CTRL_ENA		BIT(4)
14695711cd5SPawel Dembicki #define VSC73XX_CAT_DROP_FWD_PAUSE_ENA		BIT(3)
14795711cd5SPawel Dembicki #define VSC73XX_CAT_DROP_UNTAGGED_ENA		BIT(2)
14895711cd5SPawel Dembicki #define VSC73XX_CAT_DROP_TAGGED_ENA		BIT(1)
14995711cd5SPawel Dembicki #define VSC73XX_CAT_DROP_NULL_MAC_ENA		BIT(0)
15095711cd5SPawel Dembicki 
15195711cd5SPawel Dembicki #define VSC73XX_Q_MISC_CONF_EXTENT_MEM		BIT(31)
15295711cd5SPawel Dembicki #define VSC73XX_Q_MISC_CONF_EARLY_TX_MASK	GENMASK(4, 1)
15395711cd5SPawel Dembicki #define VSC73XX_Q_MISC_CONF_EARLY_TX_512	(1 << 1)
15495711cd5SPawel Dembicki #define VSC73XX_Q_MISC_CONF_MAC_PAUSE_MODE	BIT(0)
15595711cd5SPawel Dembicki 
1566b783dedSPawel Dembicki /* CAT_VLAN_MISC categorizer VLAN miscellaneous bits */
1576b783dedSPawel Dembicki #define VSC73XX_CAT_VLAN_MISC_VLAN_TCI_IGNORE_ENA BIT(8)
1586b783dedSPawel Dembicki #define VSC73XX_CAT_VLAN_MISC_VLAN_KEEP_TAG_ENA BIT(7)
1596b783dedSPawel Dembicki 
1606b783dedSPawel Dembicki /* CAT_PORT_VLAN categorizer port VLAN */
1616b783dedSPawel Dembicki #define VSC73XX_CAT_PORT_VLAN_VLAN_CFI BIT(15)
1626b783dedSPawel Dembicki #define VSC73XX_CAT_PORT_VLAN_VLAN_USR_PRIO GENMASK(14, 12)
1636b783dedSPawel Dembicki #define VSC73XX_CAT_PORT_VLAN_VLAN_VID GENMASK(11, 0)
1646b783dedSPawel Dembicki 
16595711cd5SPawel Dembicki /* Frame analyzer block 2 registers */
16695711cd5SPawel Dembicki #define VSC73XX_STORMLIMIT	0x02
16795711cd5SPawel Dembicki #define VSC73XX_ADVLEARN	0x03
16895711cd5SPawel Dembicki #define VSC73XX_IFLODMSK	0x04
16995711cd5SPawel Dembicki #define VSC73XX_VLANMASK	0x05
17095711cd5SPawel Dembicki #define VSC73XX_MACHDATA	0x06
17195711cd5SPawel Dembicki #define VSC73XX_MACLDATA	0x07
17295711cd5SPawel Dembicki #define VSC73XX_ANMOVED		0x08
17395711cd5SPawel Dembicki #define VSC73XX_ANAGEFIL	0x09
17495711cd5SPawel Dembicki #define VSC73XX_ANEVENTS	0x0a
17595711cd5SPawel Dembicki #define VSC73XX_ANCNTMASK	0x0b
17695711cd5SPawel Dembicki #define VSC73XX_ANCNTVAL	0x0c
17795711cd5SPawel Dembicki #define VSC73XX_LEARNMASK	0x0d
17895711cd5SPawel Dembicki #define VSC73XX_UFLODMASK	0x0e
17995711cd5SPawel Dembicki #define VSC73XX_MFLODMASK	0x0f
18095711cd5SPawel Dembicki #define VSC73XX_RECVMASK	0x10
18195711cd5SPawel Dembicki #define VSC73XX_AGGRCTRL	0x20
18295711cd5SPawel Dembicki #define VSC73XX_AGGRMSKS	0x30 /* Until 0x3f */
18395711cd5SPawel Dembicki #define VSC73XX_DSTMASKS	0x40 /* Until 0x7f */
18495711cd5SPawel Dembicki #define VSC73XX_SRCMASKS	0x80 /* Until 0x87 */
18595711cd5SPawel Dembicki #define VSC73XX_CAPENAB		0xa0
18695711cd5SPawel Dembicki #define VSC73XX_MACACCESS	0xb0
18795711cd5SPawel Dembicki #define VSC73XX_IPMCACCESS	0xb1
18895711cd5SPawel Dembicki #define VSC73XX_MACTINDX	0xc0
18995711cd5SPawel Dembicki #define VSC73XX_VLANACCESS	0xd0
19095711cd5SPawel Dembicki #define VSC73XX_VLANTIDX	0xe0
19195711cd5SPawel Dembicki #define VSC73XX_AGENCTRL	0xf0
19295711cd5SPawel Dembicki #define VSC73XX_CAPRST		0xff
19395711cd5SPawel Dembicki 
1941e5b23e5SPawel Dembicki #define VSC73XX_SRCMASKS_CPU_COPY		BIT(27)
1951e5b23e5SPawel Dembicki #define VSC73XX_SRCMASKS_MIRROR			BIT(26)
1961e5b23e5SPawel Dembicki #define VSC73XX_SRCMASKS_PORTS_MASK		GENMASK(7, 0)
1971e5b23e5SPawel Dembicki 
19895711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CPU_COPY		BIT(14)
19995711cd5SPawel Dembicki #define VSC73XX_MACACCESS_FWD_KILL		BIT(13)
20095711cd5SPawel Dembicki #define VSC73XX_MACACCESS_IGNORE_VLAN		BIT(12)
20195711cd5SPawel Dembicki #define VSC73XX_MACACCESS_AGED_FLAG		BIT(11)
20295711cd5SPawel Dembicki #define VSC73XX_MACACCESS_VALID			BIT(10)
20395711cd5SPawel Dembicki #define VSC73XX_MACACCESS_LOCKED		BIT(9)
20495711cd5SPawel Dembicki #define VSC73XX_MACACCESS_DEST_IDX_MASK		GENMASK(8, 3)
20595711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_MASK		GENMASK(2, 0)
20695711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_IDLE		0
20795711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_LEARN		1
20895711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_FORGET		2
20995711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_AGE_TABLE		3
21095711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_FLUSH_TABLE	4
21195711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_CLEAR_TABLE	5
21295711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_READ_ENTRY	6
21395711cd5SPawel Dembicki #define VSC73XX_MACACCESS_CMD_WRITE_ENTRY	7
21495711cd5SPawel Dembicki 
21595711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_LEARN_DISABLED	BIT(30)
21695711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_MIRROR		BIT(29)
21795711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_SRC_CHECK	BIT(28)
21895711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_PORT_MASK	GENMASK(9, 2)
2196b783dedSPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_PORT_MASK_SHIFT	2
2206b783dedSPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_MASK	GENMASK(1, 0)
22195711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_IDLE	0
22295711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_READ_ENTRY	1
22395711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_WRITE_ENTRY	2
22495711cd5SPawel Dembicki #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_CLEAR_TABLE	3
22595711cd5SPawel Dembicki 
22695711cd5SPawel Dembicki /* MII block 3 registers */
22795711cd5SPawel Dembicki #define VSC73XX_MII_STAT	0x0
22895711cd5SPawel Dembicki #define VSC73XX_MII_CMD		0x1
22995711cd5SPawel Dembicki #define VSC73XX_MII_DATA	0x2
230*8d5be2c4SPawel Dembicki #define VSC73XX_MII_MPRES	0x3
231*8d5be2c4SPawel Dembicki 
232*8d5be2c4SPawel Dembicki #define VSC73XX_MII_MPRES_NOPREAMBLE	BIT(6)
233*8d5be2c4SPawel Dembicki #define VSC73XX_MII_MPRES_PRESCALEVAL	GENMASK(5, 0)
234*8d5be2c4SPawel Dembicki #define VSC73XX_MII_PRESCALEVAL_MIN	3 /* min allowed mdio clock prescaler */
23595711cd5SPawel Dembicki 
23695711cd5SPawel Dembicki /* Arbiter block 5 registers */
23795711cd5SPawel Dembicki #define VSC73XX_ARBEMPTY		0x0c
23895711cd5SPawel Dembicki #define VSC73XX_ARBDISC			0x0e
23995711cd5SPawel Dembicki #define VSC73XX_SBACKWDROP		0x12
24095711cd5SPawel Dembicki #define VSC73XX_DBACKWDROP		0x13
24195711cd5SPawel Dembicki #define VSC73XX_ARBBURSTPROB		0x15
24295711cd5SPawel Dembicki 
24395711cd5SPawel Dembicki /* System block 7 registers */
24495711cd5SPawel Dembicki #define VSC73XX_ICPU_SIPAD		0x01
24595711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY		0x05
24695711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL		0x10
24795711cd5SPawel Dembicki #define VSC73XX_ICPU_ADDR		0x11
24895711cd5SPawel Dembicki #define VSC73XX_ICPU_SRAM		0x12
24995711cd5SPawel Dembicki #define VSC73XX_HWSEM			0x13
25095711cd5SPawel Dembicki #define VSC73XX_GLORESET		0x14
25195711cd5SPawel Dembicki #define VSC73XX_ICPU_MBOX_VAL		0x15
25295711cd5SPawel Dembicki #define VSC73XX_ICPU_MBOX_SET		0x16
25395711cd5SPawel Dembicki #define VSC73XX_ICPU_MBOX_CLR		0x17
25495711cd5SPawel Dembicki #define VSC73XX_CHIPID			0x18
25595711cd5SPawel Dembicki #define VSC73XX_GPIO			0x34
25695711cd5SPawel Dembicki 
25795711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_GTXDELAY_NONE	0
25895711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_GTXDELAY_1_4_NS	1
25995711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_GTXDELAY_1_7_NS	2
26095711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_GTXDELAY_2_0_NS	3
26195711cd5SPawel Dembicki 
26295711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_RXDELAY_NONE	(0 << 4)
26395711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_RXDELAY_1_4_NS	(1 << 4)
26495711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_RXDELAY_1_7_NS	(2 << 4)
26595711cd5SPawel Dembicki #define VSC73XX_GMIIDELAY_GMII0_RXDELAY_2_0_NS	(3 << 4)
26695711cd5SPawel Dembicki 
26795711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_WATCHDOG_RST	BIT(31)
26895711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_CLK_DIV_MASK	GENMASK(12, 8)
26995711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_SRST_HOLD	BIT(7)
27095711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_ICPU_PI_EN	BIT(6)
27195711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_BOOT_EN	BIT(3)
27295711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_EXT_ACC_EN	BIT(2)
27395711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_CLK_EN	BIT(1)
27495711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_SRST		BIT(0)
27595711cd5SPawel Dembicki 
27695711cd5SPawel Dembicki #define VSC73XX_CHIPID_ID_SHIFT		12
27795711cd5SPawel Dembicki #define VSC73XX_CHIPID_ID_MASK		0xffff
27895711cd5SPawel Dembicki #define VSC73XX_CHIPID_REV_SHIFT	28
27995711cd5SPawel Dembicki #define VSC73XX_CHIPID_REV_MASK		0xf
28095711cd5SPawel Dembicki #define VSC73XX_CHIPID_ID_7385		0x7385
28195711cd5SPawel Dembicki #define VSC73XX_CHIPID_ID_7388		0x7388
28295711cd5SPawel Dembicki #define VSC73XX_CHIPID_ID_7395		0x7395
28395711cd5SPawel Dembicki #define VSC73XX_CHIPID_ID_7398		0x7398
28495711cd5SPawel Dembicki 
28595711cd5SPawel Dembicki #define VSC73XX_GLORESET_STROBE		BIT(4)
28695711cd5SPawel Dembicki #define VSC73XX_GLORESET_ICPU_LOCK	BIT(3)
28795711cd5SPawel Dembicki #define VSC73XX_GLORESET_MEM_LOCK	BIT(2)
28895711cd5SPawel Dembicki #define VSC73XX_GLORESET_PHY_RESET	BIT(1)
28995711cd5SPawel Dembicki #define VSC73XX_GLORESET_MASTER_RESET	BIT(0)
29095711cd5SPawel Dembicki 
29195711cd5SPawel Dembicki #define VSC7385_CLOCK_DELAY		((3 << 4) | 3)
29295711cd5SPawel Dembicki #define VSC7385_CLOCK_DELAY_MASK	((3 << 4) | 3)
29395711cd5SPawel Dembicki 
29495711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_STOP	(VSC73XX_ICPU_CTRL_SRST_HOLD | \
29595711cd5SPawel Dembicki 				 VSC73XX_ICPU_CTRL_BOOT_EN | \
29695711cd5SPawel Dembicki 				 VSC73XX_ICPU_CTRL_EXT_ACC_EN)
29795711cd5SPawel Dembicki 
29895711cd5SPawel Dembicki #define VSC73XX_ICPU_CTRL_START	(VSC73XX_ICPU_CTRL_CLK_DIV | \
29995711cd5SPawel Dembicki 				 VSC73XX_ICPU_CTRL_BOOT_EN | \
30095711cd5SPawel Dembicki 				 VSC73XX_ICPU_CTRL_CLK_EN | \
30195711cd5SPawel Dembicki 				 VSC73XX_ICPU_CTRL_SRST)
30295711cd5SPawel Dembicki 
30395711cd5SPawel Dembicki #define IS_7385(a) ((a)->chipid == VSC73XX_CHIPID_ID_7385)
30495711cd5SPawel Dembicki #define IS_7388(a) ((a)->chipid == VSC73XX_CHIPID_ID_7388)
30595711cd5SPawel Dembicki #define IS_7395(a) ((a)->chipid == VSC73XX_CHIPID_ID_7395)
30695711cd5SPawel Dembicki #define IS_7398(a) ((a)->chipid == VSC73XX_CHIPID_ID_7398)
30795711cd5SPawel Dembicki #define IS_739X(a) (IS_7395(a) || IS_7398(a))
30895711cd5SPawel Dembicki 
309eb7e33d0SPawel Dembicki #define VSC73XX_POLL_SLEEP_US		1000
310eb7e33d0SPawel Dembicki #define VSC73XX_POLL_TIMEOUT_US		10000
311eb7e33d0SPawel Dembicki 
31295711cd5SPawel Dembicki struct vsc73xx_counter {
31395711cd5SPawel Dembicki 	u8 counter;
31495711cd5SPawel Dembicki 	const char *name;
31595711cd5SPawel Dembicki };
31695711cd5SPawel Dembicki 
31795711cd5SPawel Dembicki /* Counters are named according to the MIB standards where applicable.
31895711cd5SPawel Dembicki  * Some counters are custom, non-standard. The standard counters are
31995711cd5SPawel Dembicki  * named in accordance with RFC2819, RFC2021 and IEEE Std 802.3-2002 Annex
32095711cd5SPawel Dembicki  * 30A Counters.
32195711cd5SPawel Dembicki  */
32295711cd5SPawel Dembicki static const struct vsc73xx_counter vsc73xx_rx_counters[] = {
32395711cd5SPawel Dembicki 	{ 0, "RxEtherStatsPkts" },
32495711cd5SPawel Dembicki 	{ 1, "RxBroadcast+MulticastPkts" }, /* non-standard counter */
32595711cd5SPawel Dembicki 	{ 2, "RxTotalErrorPackets" }, /* non-standard counter */
32695711cd5SPawel Dembicki 	{ 3, "RxEtherStatsBroadcastPkts" },
32795711cd5SPawel Dembicki 	{ 4, "RxEtherStatsMulticastPkts" },
32895711cd5SPawel Dembicki 	{ 5, "RxEtherStatsPkts64Octets" },
32995711cd5SPawel Dembicki 	{ 6, "RxEtherStatsPkts65to127Octets" },
33095711cd5SPawel Dembicki 	{ 7, "RxEtherStatsPkts128to255Octets" },
33195711cd5SPawel Dembicki 	{ 8, "RxEtherStatsPkts256to511Octets" },
33295711cd5SPawel Dembicki 	{ 9, "RxEtherStatsPkts512to1023Octets" },
33395711cd5SPawel Dembicki 	{ 10, "RxEtherStatsPkts1024to1518Octets" },
33495711cd5SPawel Dembicki 	{ 11, "RxJumboFrames" }, /* non-standard counter */
33595711cd5SPawel Dembicki 	{ 12, "RxaPauseMACControlFramesTransmitted" },
33695711cd5SPawel Dembicki 	{ 13, "RxFIFODrops" }, /* non-standard counter */
33795711cd5SPawel Dembicki 	{ 14, "RxBackwardDrops" }, /* non-standard counter */
33895711cd5SPawel Dembicki 	{ 15, "RxClassifierDrops" }, /* non-standard counter */
33995711cd5SPawel Dembicki 	{ 16, "RxEtherStatsCRCAlignErrors" },
34095711cd5SPawel Dembicki 	{ 17, "RxEtherStatsUndersizePkts" },
34195711cd5SPawel Dembicki 	{ 18, "RxEtherStatsOversizePkts" },
34295711cd5SPawel Dembicki 	{ 19, "RxEtherStatsFragments" },
34395711cd5SPawel Dembicki 	{ 20, "RxEtherStatsJabbers" },
34495711cd5SPawel Dembicki 	{ 21, "RxaMACControlFramesReceived" },
34595711cd5SPawel Dembicki 	/* 22-24 are undefined */
34695711cd5SPawel Dembicki 	{ 25, "RxaFramesReceivedOK" },
34795711cd5SPawel Dembicki 	{ 26, "RxQoSClass0" }, /* non-standard counter */
34895711cd5SPawel Dembicki 	{ 27, "RxQoSClass1" }, /* non-standard counter */
34995711cd5SPawel Dembicki 	{ 28, "RxQoSClass2" }, /* non-standard counter */
35095711cd5SPawel Dembicki 	{ 29, "RxQoSClass3" }, /* non-standard counter */
35195711cd5SPawel Dembicki };
35295711cd5SPawel Dembicki 
35395711cd5SPawel Dembicki static const struct vsc73xx_counter vsc73xx_tx_counters[] = {
35495711cd5SPawel Dembicki 	{ 0, "TxEtherStatsPkts" },
35595711cd5SPawel Dembicki 	{ 1, "TxBroadcast+MulticastPkts" }, /* non-standard counter */
35695711cd5SPawel Dembicki 	{ 2, "TxTotalErrorPackets" }, /* non-standard counter */
35795711cd5SPawel Dembicki 	{ 3, "TxEtherStatsBroadcastPkts" },
35895711cd5SPawel Dembicki 	{ 4, "TxEtherStatsMulticastPkts" },
35995711cd5SPawel Dembicki 	{ 5, "TxEtherStatsPkts64Octets" },
36095711cd5SPawel Dembicki 	{ 6, "TxEtherStatsPkts65to127Octets" },
36195711cd5SPawel Dembicki 	{ 7, "TxEtherStatsPkts128to255Octets" },
36295711cd5SPawel Dembicki 	{ 8, "TxEtherStatsPkts256to511Octets" },
36395711cd5SPawel Dembicki 	{ 9, "TxEtherStatsPkts512to1023Octets" },
36495711cd5SPawel Dembicki 	{ 10, "TxEtherStatsPkts1024to1518Octets" },
36595711cd5SPawel Dembicki 	{ 11, "TxJumboFrames" }, /* non-standard counter */
36695711cd5SPawel Dembicki 	{ 12, "TxaPauseMACControlFramesTransmitted" },
36795711cd5SPawel Dembicki 	{ 13, "TxFIFODrops" }, /* non-standard counter */
36895711cd5SPawel Dembicki 	{ 14, "TxDrops" }, /* non-standard counter */
36995711cd5SPawel Dembicki 	{ 15, "TxEtherStatsCollisions" },
37095711cd5SPawel Dembicki 	{ 16, "TxEtherStatsCRCAlignErrors" },
37195711cd5SPawel Dembicki 	{ 17, "TxEtherStatsUndersizePkts" },
37295711cd5SPawel Dembicki 	{ 18, "TxEtherStatsOversizePkts" },
37395711cd5SPawel Dembicki 	{ 19, "TxEtherStatsFragments" },
37495711cd5SPawel Dembicki 	{ 20, "TxEtherStatsJabbers" },
37595711cd5SPawel Dembicki 	/* 21-24 are undefined */
37695711cd5SPawel Dembicki 	{ 25, "TxaFramesReceivedOK" },
37795711cd5SPawel Dembicki 	{ 26, "TxQoSClass0" }, /* non-standard counter */
37895711cd5SPawel Dembicki 	{ 27, "TxQoSClass1" }, /* non-standard counter */
37995711cd5SPawel Dembicki 	{ 28, "TxQoSClass2" }, /* non-standard counter */
38095711cd5SPawel Dembicki 	{ 29, "TxQoSClass3" }, /* non-standard counter */
38195711cd5SPawel Dembicki };
38295711cd5SPawel Dembicki 
3836b783dedSPawel Dembicki struct vsc73xx_vlan_summary {
3846b783dedSPawel Dembicki 	size_t num_tagged;
3856b783dedSPawel Dembicki 	size_t num_untagged;
3866b783dedSPawel Dembicki };
3876b783dedSPawel Dembicki 
3886b783dedSPawel Dembicki enum vsc73xx_port_vlan_conf {
3896b783dedSPawel Dembicki 	VSC73XX_VLAN_FILTER,
3906b783dedSPawel Dembicki 	VSC73XX_VLAN_FILTER_UNTAG_ALL,
3916b783dedSPawel Dembicki 	VSC73XX_VLAN_IGNORE,
3926b783dedSPawel Dembicki };
3936b783dedSPawel Dembicki 
39495711cd5SPawel Dembicki int vsc73xx_is_addr_valid(u8 block, u8 subblock)
39595711cd5SPawel Dembicki {
39695711cd5SPawel Dembicki 	switch (block) {
39795711cd5SPawel Dembicki 	case VSC73XX_BLOCK_MAC:
39895711cd5SPawel Dembicki 		switch (subblock) {
39995711cd5SPawel Dembicki 		case 0 ... 4:
40095711cd5SPawel Dembicki 		case 6:
40195711cd5SPawel Dembicki 			return 1;
40295711cd5SPawel Dembicki 		}
40395711cd5SPawel Dembicki 		break;
40495711cd5SPawel Dembicki 
40595711cd5SPawel Dembicki 	case VSC73XX_BLOCK_ANALYZER:
40695711cd5SPawel Dembicki 	case VSC73XX_BLOCK_SYSTEM:
40795711cd5SPawel Dembicki 		switch (subblock) {
40895711cd5SPawel Dembicki 		case 0:
40995711cd5SPawel Dembicki 			return 1;
41095711cd5SPawel Dembicki 		}
41195711cd5SPawel Dembicki 		break;
41295711cd5SPawel Dembicki 
41395711cd5SPawel Dembicki 	case VSC73XX_BLOCK_MII:
41495711cd5SPawel Dembicki 	case VSC73XX_BLOCK_CAPTURE:
41595711cd5SPawel Dembicki 	case VSC73XX_BLOCK_ARBITER:
41695711cd5SPawel Dembicki 		switch (subblock) {
41795711cd5SPawel Dembicki 		case 0 ... 1:
41895711cd5SPawel Dembicki 			return 1;
41995711cd5SPawel Dembicki 		}
42095711cd5SPawel Dembicki 		break;
42195711cd5SPawel Dembicki 	}
42295711cd5SPawel Dembicki 
42395711cd5SPawel Dembicki 	return 0;
42495711cd5SPawel Dembicki }
42595711cd5SPawel Dembicki EXPORT_SYMBOL(vsc73xx_is_addr_valid);
42695711cd5SPawel Dembicki 
42795711cd5SPawel Dembicki static int vsc73xx_read(struct vsc73xx *vsc, u8 block, u8 subblock, u8 reg,
42895711cd5SPawel Dembicki 			u32 *val)
42995711cd5SPawel Dembicki {
43095711cd5SPawel Dembicki 	return vsc->ops->read(vsc, block, subblock, reg, val);
43195711cd5SPawel Dembicki }
43295711cd5SPawel Dembicki 
43395711cd5SPawel Dembicki static int vsc73xx_write(struct vsc73xx *vsc, u8 block, u8 subblock, u8 reg,
43495711cd5SPawel Dembicki 			 u32 val)
43595711cd5SPawel Dembicki {
43695711cd5SPawel Dembicki 	return vsc->ops->write(vsc, block, subblock, reg, val);
43795711cd5SPawel Dembicki }
43895711cd5SPawel Dembicki 
43995711cd5SPawel Dembicki static int vsc73xx_update_bits(struct vsc73xx *vsc, u8 block, u8 subblock,
44095711cd5SPawel Dembicki 			       u8 reg, u32 mask, u32 val)
44195711cd5SPawel Dembicki {
44295711cd5SPawel Dembicki 	u32 tmp, orig;
44395711cd5SPawel Dembicki 	int ret;
44495711cd5SPawel Dembicki 
44595711cd5SPawel Dembicki 	/* Same read-modify-write algorithm as e.g. regmap */
44695711cd5SPawel Dembicki 	ret = vsc73xx_read(vsc, block, subblock, reg, &orig);
44795711cd5SPawel Dembicki 	if (ret)
44895711cd5SPawel Dembicki 		return ret;
44995711cd5SPawel Dembicki 	tmp = orig & ~mask;
45095711cd5SPawel Dembicki 	tmp |= val & mask;
45195711cd5SPawel Dembicki 	return vsc73xx_write(vsc, block, subblock, reg, tmp);
45295711cd5SPawel Dembicki }
45395711cd5SPawel Dembicki 
45495711cd5SPawel Dembicki static int vsc73xx_detect(struct vsc73xx *vsc)
45595711cd5SPawel Dembicki {
45695711cd5SPawel Dembicki 	bool icpu_si_boot_en;
45795711cd5SPawel Dembicki 	bool icpu_pi_en;
45895711cd5SPawel Dembicki 	u32 val;
45995711cd5SPawel Dembicki 	u32 rev;
46095711cd5SPawel Dembicki 	int ret;
46195711cd5SPawel Dembicki 	u32 id;
46295711cd5SPawel Dembicki 
46395711cd5SPawel Dembicki 	ret = vsc73xx_read(vsc, VSC73XX_BLOCK_SYSTEM, 0,
46495711cd5SPawel Dembicki 			   VSC73XX_ICPU_MBOX_VAL, &val);
46595711cd5SPawel Dembicki 	if (ret) {
46695711cd5SPawel Dembicki 		dev_err(vsc->dev, "unable to read mailbox (%d)\n", ret);
46795711cd5SPawel Dembicki 		return ret;
46895711cd5SPawel Dembicki 	}
46995711cd5SPawel Dembicki 
47095711cd5SPawel Dembicki 	if (val == 0xffffffff) {
4711da39ff0SPawel Dembicki 		dev_info(vsc->dev, "chip seems dead.\n");
4721da39ff0SPawel Dembicki 		return -EAGAIN;
47395711cd5SPawel Dembicki 	}
47495711cd5SPawel Dembicki 
47595711cd5SPawel Dembicki 	ret = vsc73xx_read(vsc, VSC73XX_BLOCK_SYSTEM, 0,
47695711cd5SPawel Dembicki 			   VSC73XX_CHIPID, &val);
47795711cd5SPawel Dembicki 	if (ret) {
47895711cd5SPawel Dembicki 		dev_err(vsc->dev, "unable to read chip id (%d)\n", ret);
47995711cd5SPawel Dembicki 		return ret;
48095711cd5SPawel Dembicki 	}
48195711cd5SPawel Dembicki 
48295711cd5SPawel Dembicki 	id = (val >> VSC73XX_CHIPID_ID_SHIFT) &
48395711cd5SPawel Dembicki 		VSC73XX_CHIPID_ID_MASK;
48495711cd5SPawel Dembicki 	switch (id) {
48595711cd5SPawel Dembicki 	case VSC73XX_CHIPID_ID_7385:
48695711cd5SPawel Dembicki 	case VSC73XX_CHIPID_ID_7388:
48795711cd5SPawel Dembicki 	case VSC73XX_CHIPID_ID_7395:
48895711cd5SPawel Dembicki 	case VSC73XX_CHIPID_ID_7398:
48995711cd5SPawel Dembicki 		break;
49095711cd5SPawel Dembicki 	default:
49195711cd5SPawel Dembicki 		dev_err(vsc->dev, "unsupported chip, id=%04x\n", id);
49295711cd5SPawel Dembicki 		return -ENODEV;
49395711cd5SPawel Dembicki 	}
49495711cd5SPawel Dembicki 
49595711cd5SPawel Dembicki 	vsc->chipid = id;
49695711cd5SPawel Dembicki 	rev = (val >> VSC73XX_CHIPID_REV_SHIFT) &
49795711cd5SPawel Dembicki 		VSC73XX_CHIPID_REV_MASK;
49895711cd5SPawel Dembicki 	dev_info(vsc->dev, "VSC%04X (rev: %d) switch found\n", id, rev);
49995711cd5SPawel Dembicki 
50095711cd5SPawel Dembicki 	ret = vsc73xx_read(vsc, VSC73XX_BLOCK_SYSTEM, 0,
50195711cd5SPawel Dembicki 			   VSC73XX_ICPU_CTRL, &val);
50295711cd5SPawel Dembicki 	if (ret) {
50395711cd5SPawel Dembicki 		dev_err(vsc->dev, "unable to read iCPU control\n");
50495711cd5SPawel Dembicki 		return ret;
50595711cd5SPawel Dembicki 	}
50695711cd5SPawel Dembicki 
50795711cd5SPawel Dembicki 	/* The iCPU can always be used but can boot in different ways.
50895711cd5SPawel Dembicki 	 * If it is initially disabled and has no external memory,
50995711cd5SPawel Dembicki 	 * we are in control and can do whatever we like, else we
51095711cd5SPawel Dembicki 	 * are probably in trouble (we need some way to communicate
51195711cd5SPawel Dembicki 	 * with the running firmware) so we bail out for now.
51295711cd5SPawel Dembicki 	 */
51395711cd5SPawel Dembicki 	icpu_pi_en = !!(val & VSC73XX_ICPU_CTRL_ICPU_PI_EN);
51495711cd5SPawel Dembicki 	icpu_si_boot_en = !!(val & VSC73XX_ICPU_CTRL_BOOT_EN);
51595711cd5SPawel Dembicki 	if (icpu_si_boot_en && icpu_pi_en) {
51695711cd5SPawel Dembicki 		dev_err(vsc->dev,
51795711cd5SPawel Dembicki 			"iCPU enabled boots from SI, has external memory\n");
51895711cd5SPawel Dembicki 		dev_err(vsc->dev, "no idea how to deal with this\n");
51995711cd5SPawel Dembicki 		return -ENODEV;
52095711cd5SPawel Dembicki 	}
52195711cd5SPawel Dembicki 	if (icpu_si_boot_en && !icpu_pi_en) {
52295711cd5SPawel Dembicki 		dev_err(vsc->dev,
5231da39ff0SPawel Dembicki 			"iCPU enabled boots from PI/SI, no external memory\n");
5241da39ff0SPawel Dembicki 		return -EAGAIN;
52595711cd5SPawel Dembicki 	}
52695711cd5SPawel Dembicki 	if (!icpu_si_boot_en && icpu_pi_en) {
52795711cd5SPawel Dembicki 		dev_err(vsc->dev,
52895711cd5SPawel Dembicki 			"iCPU enabled, boots from PI external memory\n");
52995711cd5SPawel Dembicki 		dev_err(vsc->dev, "no idea how to deal with this\n");
53095711cd5SPawel Dembicki 		return -ENODEV;
53195711cd5SPawel Dembicki 	}
53295711cd5SPawel Dembicki 	/* !icpu_si_boot_en && !cpu_pi_en */
53395711cd5SPawel Dembicki 	dev_info(vsc->dev, "iCPU disabled, no external memory\n");
53495711cd5SPawel Dembicki 
53595711cd5SPawel Dembicki 	return 0;
53695711cd5SPawel Dembicki }
53795711cd5SPawel Dembicki 
53895711cd5SPawel Dembicki static int vsc73xx_phy_read(struct dsa_switch *ds, int phy, int regnum)
53995711cd5SPawel Dembicki {
54095711cd5SPawel Dembicki 	struct vsc73xx *vsc = ds->priv;
54195711cd5SPawel Dembicki 	u32 cmd;
54295711cd5SPawel Dembicki 	u32 val;
54395711cd5SPawel Dembicki 	int ret;
54495711cd5SPawel Dembicki 
54595711cd5SPawel Dembicki 	/* Setting bit 26 means "read" */
54695711cd5SPawel Dembicki 	cmd = BIT(26) | (phy << 21) | (regnum << 16);
54795711cd5SPawel Dembicki 	ret = vsc73xx_write(vsc, VSC73XX_BLOCK_MII, 0, 1, cmd);
54895711cd5SPawel Dembicki 	if (ret)
54995711cd5SPawel Dembicki 		return ret;
55095711cd5SPawel Dembicki 	msleep(2);
55195711cd5SPawel Dembicki 	ret = vsc73xx_read(vsc, VSC73XX_BLOCK_MII, 0, 2, &val);
55295711cd5SPawel Dembicki 	if (ret)
55395711cd5SPawel Dembicki 		return ret;
55495711cd5SPawel Dembicki 	if (val & BIT(16)) {
55595711cd5SPawel Dembicki 		dev_err(vsc->dev, "reading reg %02x from phy%d failed\n",
55695711cd5SPawel Dembicki 			regnum, phy);
55795711cd5SPawel Dembicki 		return -EIO;
55895711cd5SPawel Dembicki 	}
55995711cd5SPawel Dembicki 	val &= 0xFFFFU;
56095711cd5SPawel Dembicki 
56195711cd5SPawel Dembicki 	dev_dbg(vsc->dev, "read reg %02x from phy%d = %04x\n",
56295711cd5SPawel Dembicki 		regnum, phy, val);
56395711cd5SPawel Dembicki 
56495711cd5SPawel Dembicki 	return val;
56595711cd5SPawel Dembicki }
56695711cd5SPawel Dembicki 
56795711cd5SPawel Dembicki static int vsc73xx_phy_write(struct dsa_switch *ds, int phy, int regnum,
56895711cd5SPawel Dembicki 			     u16 val)
56995711cd5SPawel Dembicki {
57095711cd5SPawel Dembicki 	struct vsc73xx *vsc = ds->priv;
57195711cd5SPawel Dembicki 	u32 cmd;
57295711cd5SPawel Dembicki 	int ret;
57395711cd5SPawel Dembicki 
57495711cd5SPawel Dembicki 	/* It was found through tedious experiments that this router
57595711cd5SPawel Dembicki 	 * chip really hates to have it's PHYs reset. They
57695711cd5SPawel Dembicki 	 * never recover if that happens: autonegotiation stops
57795711cd5SPawel Dembicki 	 * working after a reset. Just filter out this command.
57895711cd5SPawel Dembicki 	 * (Resetting the whole chip is OK.)
57995711cd5SPawel Dembicki 	 */
58095711cd5SPawel Dembicki 	if (regnum == 0 && (val & BIT(15))) {
58195711cd5SPawel Dembicki 		dev_info(vsc->dev, "reset PHY - disallowed\n");
58295711cd5SPawel Dembicki 		return 0;
58395711cd5SPawel Dembicki 	}
58495711cd5SPawel Dembicki 
58595711cd5SPawel Dembicki 	cmd = (phy << 21) | (regnum << 16);
58695711cd5SPawel Dembicki 	ret = vsc73xx_write(vsc, VSC73XX_BLOCK_MII, 0, 1, cmd);
58795711cd5SPawel Dembicki 	if (ret)
58895711cd5SPawel Dembicki 		return ret;
58995711cd5SPawel Dembicki 
59095711cd5SPawel Dembicki 	dev_dbg(vsc->dev, "write %04x to reg %02x in phy%d\n",
59195711cd5SPawel Dembicki 		val, regnum, phy);
59295711cd5SPawel Dembicki 	return 0;
59395711cd5SPawel Dembicki }
59495711cd5SPawel Dembicki 
59595711cd5SPawel Dembicki static enum dsa_tag_protocol vsc73xx_get_tag_protocol(struct dsa_switch *ds,
5964d776482SFlorian Fainelli 						      int port,
5974d776482SFlorian Fainelli 						      enum dsa_tag_protocol mp)
59895711cd5SPawel Dembicki {
59995711cd5SPawel Dembicki 	/* The switch internally uses a 8 byte header with length,
60095711cd5SPawel Dembicki 	 * source port, tag, LPA and priority. This is supposedly
60195711cd5SPawel Dembicki 	 * only accessible when operating the switch using the internal
60295711cd5SPawel Dembicki 	 * CPU or with an external CPU mapping the device in, but not
60395711cd5SPawel Dembicki 	 * when operating the switch over SPI and putting frames in/out
60495711cd5SPawel Dembicki 	 * on port 6 (the CPU port). So far we must assume that we
60595711cd5SPawel Dembicki 	 * cannot access the tag. (See "Internal frame header" section
60695711cd5SPawel Dembicki 	 * 3.9.1 in the manual.)
60795711cd5SPawel Dembicki 	 */
608e3386ec4SPawel Dembicki 	return DSA_TAG_PROTO_VSC73XX_8021Q;
60995711cd5SPawel Dembicki }
61095711cd5SPawel Dembicki 
6116b783dedSPawel Dembicki static int vsc73xx_wait_for_vlan_table_cmd(struct vsc73xx *vsc)
6126b783dedSPawel Dembicki {
6136b783dedSPawel Dembicki 	int ret, err;
6146b783dedSPawel Dembicki 	u32 val;
6156b783dedSPawel Dembicki 
6166b783dedSPawel Dembicki 	ret = read_poll_timeout(vsc73xx_read, err,
6176b783dedSPawel Dembicki 				err < 0 ||
6186b783dedSPawel Dembicki 				((val & VSC73XX_VLANACCESS_VLAN_TBL_CMD_MASK) ==
6196b783dedSPawel Dembicki 				VSC73XX_VLANACCESS_VLAN_TBL_CMD_IDLE),
6206b783dedSPawel Dembicki 				VSC73XX_POLL_SLEEP_US, VSC73XX_POLL_TIMEOUT_US,
6216b783dedSPawel Dembicki 				false, vsc, VSC73XX_BLOCK_ANALYZER,
6226b783dedSPawel Dembicki 				0, VSC73XX_VLANACCESS, &val);
6236b783dedSPawel Dembicki 	if (ret)
6246b783dedSPawel Dembicki 		return ret;
6256b783dedSPawel Dembicki 	return err;
6266b783dedSPawel Dembicki }
6276b783dedSPawel Dembicki 
6286b783dedSPawel Dembicki static int
6296b783dedSPawel Dembicki vsc73xx_read_vlan_table_entry(struct vsc73xx *vsc, u16 vid, u8 *portmap)
6306b783dedSPawel Dembicki {
6316b783dedSPawel Dembicki 	u32 val;
6326b783dedSPawel Dembicki 	int ret;
6336b783dedSPawel Dembicki 
6346b783dedSPawel Dembicki 	vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANTIDX, vid);
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_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANACCESS,
6416b783dedSPawel Dembicki 			    VSC73XX_VLANACCESS_VLAN_TBL_CMD_MASK,
6426b783dedSPawel Dembicki 			    VSC73XX_VLANACCESS_VLAN_TBL_CMD_READ_ENTRY);
6436b783dedSPawel Dembicki 
6446b783dedSPawel Dembicki 	ret = vsc73xx_wait_for_vlan_table_cmd(vsc);
6456b783dedSPawel Dembicki 	if (ret)
6466b783dedSPawel Dembicki 		return ret;
6476b783dedSPawel Dembicki 
6486b783dedSPawel Dembicki 	vsc73xx_read(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANACCESS, &val);
6496b783dedSPawel Dembicki 	*portmap = (val & VSC73XX_VLANACCESS_VLAN_PORT_MASK) >>
6506b783dedSPawel Dembicki 		   VSC73XX_VLANACCESS_VLAN_PORT_MASK_SHIFT;
6516b783dedSPawel Dembicki 
6526b783dedSPawel Dembicki 	return 0;
6536b783dedSPawel Dembicki }
6546b783dedSPawel Dembicki 
6556b783dedSPawel Dembicki static int
6566b783dedSPawel Dembicki vsc73xx_write_vlan_table_entry(struct vsc73xx *vsc, u16 vid, u8 portmap)
6576b783dedSPawel Dembicki {
6586b783dedSPawel Dembicki 	int ret;
6596b783dedSPawel Dembicki 
6606b783dedSPawel Dembicki 	vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANTIDX, vid);
6616b783dedSPawel Dembicki 
6626b783dedSPawel Dembicki 	ret = vsc73xx_wait_for_vlan_table_cmd(vsc);
6636b783dedSPawel Dembicki 	if (ret)
6646b783dedSPawel Dembicki 		return ret;
6656b783dedSPawel Dembicki 
6666b783dedSPawel Dembicki 	vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANACCESS,
6676b783dedSPawel Dembicki 			    VSC73XX_VLANACCESS_VLAN_TBL_CMD_MASK |
6686b783dedSPawel Dembicki 			    VSC73XX_VLANACCESS_VLAN_SRC_CHECK |
6696b783dedSPawel Dembicki 			    VSC73XX_VLANACCESS_VLAN_PORT_MASK,
6706b783dedSPawel Dembicki 			    VSC73XX_VLANACCESS_VLAN_TBL_CMD_WRITE_ENTRY |
6716b783dedSPawel Dembicki 			    VSC73XX_VLANACCESS_VLAN_SRC_CHECK |
6726b783dedSPawel Dembicki 			    (portmap << VSC73XX_VLANACCESS_VLAN_PORT_MASK_SHIFT));
6736b783dedSPawel Dembicki 
6746b783dedSPawel Dembicki 	return vsc73xx_wait_for_vlan_table_cmd(vsc);
6756b783dedSPawel Dembicki }
6766b783dedSPawel Dembicki 
6776b783dedSPawel Dembicki static int
6786b783dedSPawel Dembicki vsc73xx_update_vlan_table(struct vsc73xx *vsc, int port, u16 vid, bool set)
6796b783dedSPawel Dembicki {
6806b783dedSPawel Dembicki 	u8 portmap;
6816b783dedSPawel Dembicki 	int ret;
6826b783dedSPawel Dembicki 
6836b783dedSPawel Dembicki 	ret = vsc73xx_read_vlan_table_entry(vsc, vid, &portmap);
6846b783dedSPawel Dembicki 	if (ret)
6856b783dedSPawel Dembicki 		return ret;
6866b783dedSPawel Dembicki 
6876b783dedSPawel Dembicki 	if (set)
6886b783dedSPawel Dembicki 		portmap |= BIT(port);
6896b783dedSPawel Dembicki 	else
6906b783dedSPawel Dembicki 		portmap &= ~BIT(port);
6916b783dedSPawel Dembicki 
6926b783dedSPawel Dembicki 	return vsc73xx_write_vlan_table_entry(vsc, vid, portmap);
6936b783dedSPawel Dembicki }
6946b783dedSPawel Dembicki 
6953b91b032SPawel Dembicki static int vsc73xx_configure_rgmii_port_delay(struct dsa_switch *ds)
6963b91b032SPawel Dembicki {
6973b91b032SPawel Dembicki 	/* Keep 2.0 ns delay for backward complatibility */
6983b91b032SPawel Dembicki 	u32 tx_delay = VSC73XX_GMIIDELAY_GMII0_GTXDELAY_2_0_NS;
6993b91b032SPawel Dembicki 	u32 rx_delay = VSC73XX_GMIIDELAY_GMII0_RXDELAY_2_0_NS;
7003b91b032SPawel Dembicki 	struct dsa_port *dp = dsa_to_port(ds, CPU_PORT);
7013b91b032SPawel Dembicki 	struct device_node *port_dn = dp->dn;
7023b91b032SPawel Dembicki 	struct vsc73xx *vsc = ds->priv;
7033b91b032SPawel Dembicki 	u32 delay;
7043b91b032SPawel Dembicki 
7053b91b032SPawel Dembicki 	if (!of_property_read_u32(port_dn, "tx-internal-delay-ps", &delay)) {
7063b91b032SPawel Dembicki 		switch (delay) {
7073b91b032SPawel Dembicki 		case 0:
7083b91b032SPawel Dembicki 			tx_delay = VSC73XX_GMIIDELAY_GMII0_GTXDELAY_NONE;
7093b91b032SPawel Dembicki 			break;
7103b91b032SPawel Dembicki 		case 1400:
7113b91b032SPawel Dembicki 			tx_delay = VSC73XX_GMIIDELAY_GMII0_GTXDELAY_1_4_NS;
7123b91b032SPawel Dembicki 			break;
7133b91b032SPawel Dembicki 		case 1700:
7143b91b032SPawel Dembicki 			tx_delay = VSC73XX_GMIIDELAY_GMII0_GTXDELAY_1_7_NS;
7153b91b032SPawel Dembicki 			break;
7163b91b032SPawel Dembicki 		case 2000:
7173b91b032SPawel Dembicki 			break;
7183b91b032SPawel Dembicki 		default:
7193b91b032SPawel Dembicki 			dev_err(vsc->dev,
7203b91b032SPawel Dembicki 				"Unsupported RGMII Transmit Clock Delay\n");
7213b91b032SPawel Dembicki 			return -EINVAL;
7223b91b032SPawel Dembicki 		}
7233b91b032SPawel Dembicki 	} else {
7243b91b032SPawel Dembicki 		dev_dbg(vsc->dev,
7253b91b032SPawel Dembicki 			"RGMII Transmit Clock Delay isn't configured, set to 2.0 ns\n");
7263b91b032SPawel Dembicki 	}
7273b91b032SPawel Dembicki 
7283b91b032SPawel Dembicki 	if (!of_property_read_u32(port_dn, "rx-internal-delay-ps", &delay)) {
7293b91b032SPawel Dembicki 		switch (delay) {
7303b91b032SPawel Dembicki 		case 0:
7313b91b032SPawel Dembicki 			rx_delay = VSC73XX_GMIIDELAY_GMII0_RXDELAY_NONE;
7323b91b032SPawel Dembicki 			break;
7333b91b032SPawel Dembicki 		case 1400:
7343b91b032SPawel Dembicki 			rx_delay = VSC73XX_GMIIDELAY_GMII0_RXDELAY_1_4_NS;
7353b91b032SPawel Dembicki 			break;
7363b91b032SPawel Dembicki 		case 1700:
7373b91b032SPawel Dembicki 			rx_delay = VSC73XX_GMIIDELAY_GMII0_RXDELAY_1_7_NS;
7383b91b032SPawel Dembicki 			break;
7393b91b032SPawel Dembicki 		case 2000:
7403b91b032SPawel Dembicki 			break;
7413b91b032SPawel Dembicki 		default:
7423b91b032SPawel Dembicki 			dev_err(vsc->dev,
7433b91b032SPawel Dembicki 				"Unsupported RGMII Receive Clock Delay value\n");
7443b91b032SPawel Dembicki 			return -EINVAL;
7453b91b032SPawel Dembicki 		}
7463b91b032SPawel Dembicki 	} else {
7473b91b032SPawel Dembicki 		dev_dbg(vsc->dev,
7483b91b032SPawel Dembicki 			"RGMII Receive Clock Delay isn't configured, set to 2.0 ns\n");
7493b91b032SPawel Dembicki 	}
7503b91b032SPawel Dembicki 
7513b91b032SPawel Dembicki 	/* MII delay, set both GTX and RX delay */
7523b91b032SPawel Dembicki 	return vsc73xx_write(vsc, VSC73XX_BLOCK_SYSTEM, 0, VSC73XX_GMIIDELAY,
7533b91b032SPawel Dembicki 			     tx_delay | rx_delay);
7543b91b032SPawel Dembicki }
7553b91b032SPawel Dembicki 
75695711cd5SPawel Dembicki static int vsc73xx_setup(struct dsa_switch *ds)
75795711cd5SPawel Dembicki {
75895711cd5SPawel Dembicki 	struct vsc73xx *vsc = ds->priv;
759*8d5be2c4SPawel Dembicki 	int i, ret, val;
76095711cd5SPawel Dembicki 
76195711cd5SPawel Dembicki 	dev_info(vsc->dev, "set up the switch\n");
76295711cd5SPawel Dembicki 
7636dfaaa27SPawel Dembicki 	ds->untag_bridge_pvid = true;
7646dfaaa27SPawel Dembicki 	ds->max_num_bridges = DSA_TAG_8021Q_MAX_NUM_BRIDGES;
7656dfaaa27SPawel Dembicki 
76695711cd5SPawel Dembicki 	/* Issue RESET */
76795711cd5SPawel Dembicki 	vsc73xx_write(vsc, VSC73XX_BLOCK_SYSTEM, 0, VSC73XX_GLORESET,
76895711cd5SPawel Dembicki 		      VSC73XX_GLORESET_MASTER_RESET);
76995711cd5SPawel Dembicki 	usleep_range(125, 200);
77095711cd5SPawel Dembicki 
77195711cd5SPawel Dembicki 	/* Initialize memory, initialize RAM bank 0..15 except 6 and 7
77295711cd5SPawel Dembicki 	 * This sequence appears in the
77395711cd5SPawel Dembicki 	 * VSC7385 SparX-G5 datasheet section 6.6.1
77495711cd5SPawel Dembicki 	 * VSC7395 SparX-G5e datasheet section 6.6.1
77595711cd5SPawel Dembicki 	 * "initialization sequence".
77695711cd5SPawel Dembicki 	 * No explanation is given to the 0x1010400 magic number.
77795711cd5SPawel Dembicki 	 */
77895711cd5SPawel Dembicki 	for (i = 0; i <= 15; i++) {
77995711cd5SPawel Dembicki 		if (i != 6 && i != 7) {
78095711cd5SPawel Dembicki 			vsc73xx_write(vsc, VSC73XX_BLOCK_MEMINIT,
78195711cd5SPawel Dembicki 				      2,
78295711cd5SPawel Dembicki 				      0, 0x1010400 + i);
78395711cd5SPawel Dembicki 			mdelay(1);
78495711cd5SPawel Dembicki 		}
78595711cd5SPawel Dembicki 	}
78695711cd5SPawel Dembicki 	mdelay(30);
78795711cd5SPawel Dembicki 
78895711cd5SPawel Dembicki 	/* Clear MAC table */
78995711cd5SPawel Dembicki 	vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0,
79095711cd5SPawel Dembicki 		      VSC73XX_MACACCESS,
79195711cd5SPawel Dembicki 		      VSC73XX_MACACCESS_CMD_CLEAR_TABLE);
79295711cd5SPawel Dembicki 
7936b783dedSPawel Dembicki 	/* Set VLAN table to default values */
79495711cd5SPawel Dembicki 	vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0,
79595711cd5SPawel Dembicki 		      VSC73XX_VLANACCESS,
79695711cd5SPawel Dembicki 		      VSC73XX_VLANACCESS_VLAN_TBL_CMD_CLEAR_TABLE);
79795711cd5SPawel Dembicki 
79895711cd5SPawel Dembicki 	msleep(40);
79995711cd5SPawel Dembicki 
80095711cd5SPawel Dembicki 	/* Use 20KiB buffers on all ports on VSC7395
80195711cd5SPawel Dembicki 	 * The VSC7385 has 16KiB buffers and that is the
80295711cd5SPawel Dembicki 	 * default if we don't set this up explicitly.
80395711cd5SPawel Dembicki 	 * Port "31" is "all ports".
80495711cd5SPawel Dembicki 	 */
80595711cd5SPawel Dembicki 	if (IS_739X(vsc))
80695711cd5SPawel Dembicki 		vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 0x1f,
80795711cd5SPawel Dembicki 			      VSC73XX_Q_MISC_CONF,
80895711cd5SPawel Dembicki 			      VSC73XX_Q_MISC_CONF_EXTENT_MEM);
80995711cd5SPawel Dembicki 
81095711cd5SPawel Dembicki 	/* Put all ports into reset until enabled */
81195711cd5SPawel Dembicki 	for (i = 0; i < 7; i++) {
81295711cd5SPawel Dembicki 		if (i == 5)
81395711cd5SPawel Dembicki 			continue;
81495711cd5SPawel Dembicki 		vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, 4,
81595711cd5SPawel Dembicki 			      VSC73XX_MAC_CFG, VSC73XX_MAC_CFG_RESET);
81695711cd5SPawel Dembicki 	}
81795711cd5SPawel Dembicki 
8183b91b032SPawel Dembicki 	/* Configure RGMII delay */
8193b91b032SPawel Dembicki 	ret = vsc73xx_configure_rgmii_port_delay(ds);
8203b91b032SPawel Dembicki 	if (ret)
8213b91b032SPawel Dembicki 		return ret;
8223b91b032SPawel Dembicki 
8236b783dedSPawel Dembicki 	/* Ingess VLAN reception mask (table 145) */
8246b783dedSPawel Dembicki 	vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_VLANMASK,
8256b783dedSPawel Dembicki 		      0xff);
82695711cd5SPawel Dembicki 	/* IP multicast flood mask (table 144) */
82795711cd5SPawel Dembicki 	vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, 0, VSC73XX_IFLODMSK,
82895711cd5SPawel Dembicki 		      0xff);
82995711cd5SPawel Dembicki 
83095711cd5SPawel Dembicki 	mdelay(50);
83195711cd5SPawel Dembicki 
832*8d5be2c4SPawel Dembicki 	/* Disable preamble and use maximum allowed clock for the internal
833*8d5be2c4SPawel Dembicki 	 * mdio bus, used for communication with internal PHYs only.
834*8d5be2c4SPawel Dembicki 	 */
835*8d5be2c4SPawel Dembicki 	val = VSC73XX_MII_MPRES_NOPREAMBLE |
836*8d5be2c4SPawel Dembicki 	      FIELD_PREP(VSC73XX_MII_MPRES_PRESCALEVAL,
837*8d5be2c4SPawel Dembicki 			 VSC73XX_MII_PRESCALEVAL_MIN);
838*8d5be2c4SPawel Dembicki 	vsc73xx_write(vsc, VSC73XX_BLOCK_MII, VSC73XX_BLOCK_MII_INTERNAL,
839*8d5be2c4SPawel Dembicki 		      VSC73XX_MII_MPRES, val);
840*8d5be2c4SPawel Dembicki 
84195711cd5SPawel Dembicki 	/* Release reset from the internal PHYs */
84295711cd5SPawel Dembicki 	vsc73xx_write(vsc, VSC73XX_BLOCK_SYSTEM, 0, VSC73XX_GLORESET,
84395711cd5SPawel Dembicki 		      VSC73XX_GLORESET_PHY_RESET);
84495711cd5SPawel Dembicki 
84595711cd5SPawel Dembicki 	udelay(4);
84695711cd5SPawel Dembicki 
8476b783dedSPawel Dembicki 	/* Clear VLAN table */
8486b783dedSPawel Dembicki 	for (i = 0; i < VLAN_N_VID; i++)
8496b783dedSPawel Dembicki 		vsc73xx_write_vlan_table_entry(vsc, i, 0);
8506b783dedSPawel Dembicki 
8516b783dedSPawel Dembicki 	INIT_LIST_HEAD(&vsc->vlans);
8526b783dedSPawel Dembicki 
853e3386ec4SPawel Dembicki 	rtnl_lock();
854e3386ec4SPawel Dembicki 	ret = dsa_tag_8021q_register(ds, htons(ETH_P_8021Q));
855e3386ec4SPawel Dembicki 	rtnl_unlock();
856e3386ec4SPawel Dembicki 
857e3386ec4SPawel Dembicki 	return ret;
858e3386ec4SPawel Dembicki }
859e3386ec4SPawel Dembicki 
860e3386ec4SPawel Dembicki static void vsc73xx_teardown(struct dsa_switch *ds)
861e3386ec4SPawel Dembicki {
862e3386ec4SPawel Dembicki 	rtnl_lock();
863e3386ec4SPawel Dembicki 	dsa_tag_8021q_unregister(ds);
864e3386ec4SPawel Dembicki 	rtnl_unlock();
86595711cd5SPawel Dembicki }
86695711cd5SPawel Dembicki 
86795711cd5SPawel Dembicki static void vsc73xx_init_port(struct vsc73xx *vsc, int port)
86895711cd5SPawel Dembicki {
86995711cd5SPawel Dembicki 	u32 val;
87095711cd5SPawel Dembicki 
87195711cd5SPawel Dembicki 	/* MAC configure, first reset the port and then write defaults */
87295711cd5SPawel Dembicki 	vsc73xx_write(vsc, VSC73XX_BLOCK_MAC,
87395711cd5SPawel Dembicki 		      port,
87495711cd5SPawel Dembicki 		      VSC73XX_MAC_CFG,
87595711cd5SPawel Dembicki 		      VSC73XX_MAC_CFG_RESET);
87695711cd5SPawel Dembicki 
87795711cd5SPawel Dembicki 	/* Take up the port in 1Gbit mode by default, this will be
87895711cd5SPawel Dembicki 	 * augmented after auto-negotiation on the PHY-facing
87995711cd5SPawel Dembicki 	 * ports.
88095711cd5SPawel Dembicki 	 */
88195711cd5SPawel Dembicki 	if (port == CPU_PORT)
88295711cd5SPawel Dembicki 		val = VSC73XX_MAC_CFG_1000M_F_RGMII;
88395711cd5SPawel Dembicki 	else
88495711cd5SPawel Dembicki 		val = VSC73XX_MAC_CFG_1000M_F_PHY;
88595711cd5SPawel Dembicki 
88695711cd5SPawel Dembicki 	vsc73xx_write(vsc, VSC73XX_BLOCK_MAC,
88795711cd5SPawel Dembicki 		      port,
88895711cd5SPawel Dembicki 		      VSC73XX_MAC_CFG,
88995711cd5SPawel Dembicki 		      val |
89095711cd5SPawel Dembicki 		      VSC73XX_MAC_CFG_TX_EN |
89195711cd5SPawel Dembicki 		      VSC73XX_MAC_CFG_RX_EN);
89295711cd5SPawel Dembicki 
89395711cd5SPawel Dembicki 	/* Flow control for the CPU port:
89495711cd5SPawel Dembicki 	 * Use a zero delay pause frame when pause condition is left
89595711cd5SPawel Dembicki 	 * Obey pause control frames
89695711cd5SPawel Dembicki 	 */
89795711cd5SPawel Dembicki 	vsc73xx_write(vsc, VSC73XX_BLOCK_MAC,
89895711cd5SPawel Dembicki 		      port,
89995711cd5SPawel Dembicki 		      VSC73XX_FCCONF,
90095711cd5SPawel Dembicki 		      VSC73XX_FCCONF_ZERO_PAUSE_EN |
90195711cd5SPawel Dembicki 		      VSC73XX_FCCONF_FLOW_CTRL_OBEY);
90295711cd5SPawel Dembicki 
90395711cd5SPawel Dembicki 	/* Issue pause control frames on PHY facing ports.
90495711cd5SPawel Dembicki 	 * Allow early initiation of MAC transmission if the amount
90595711cd5SPawel Dembicki 	 * of egress data is below 512 bytes on CPU port.
90695711cd5SPawel Dembicki 	 * FIXME: enable 20KiB buffers?
90795711cd5SPawel Dembicki 	 */
90895711cd5SPawel Dembicki 	if (port == CPU_PORT)
90995711cd5SPawel Dembicki 		val = VSC73XX_Q_MISC_CONF_EARLY_TX_512;
91095711cd5SPawel Dembicki 	else
91195711cd5SPawel Dembicki 		val = VSC73XX_Q_MISC_CONF_MAC_PAUSE_MODE;
91295711cd5SPawel Dembicki 	val |= VSC73XX_Q_MISC_CONF_EXTENT_MEM;
91395711cd5SPawel Dembicki 	vsc73xx_write(vsc, VSC73XX_BLOCK_MAC,
91495711cd5SPawel Dembicki 		      port,
91595711cd5SPawel Dembicki 		      VSC73XX_Q_MISC_CONF,
91695711cd5SPawel Dembicki 		      val);
91795711cd5SPawel Dembicki 
91895711cd5SPawel Dembicki 	/* Flow control MAC: a MAC address used in flow control frames */
91995711cd5SPawel Dembicki 	val = (vsc->addr[5] << 16) | (vsc->addr[4] << 8) | (vsc->addr[3]);
92095711cd5SPawel Dembicki 	vsc73xx_write(vsc, VSC73XX_BLOCK_MAC,
92195711cd5SPawel Dembicki 		      port,
92295711cd5SPawel Dembicki 		      VSC73XX_FCMACHI,
92395711cd5SPawel Dembicki 		      val);
92495711cd5SPawel Dembicki 	val = (vsc->addr[2] << 16) | (vsc->addr[1] << 8) | (vsc->addr[0]);
92595711cd5SPawel Dembicki 	vsc73xx_write(vsc, VSC73XX_BLOCK_MAC,
92695711cd5SPawel Dembicki 		      port,
92795711cd5SPawel Dembicki 		      VSC73XX_FCMACLO,
92895711cd5SPawel Dembicki 		      val);
92995711cd5SPawel Dembicki 
93095711cd5SPawel Dembicki 	/* Tell the categorizer to forward pause frames, not control
93195711cd5SPawel Dembicki 	 * frame. Do not drop anything.
93295711cd5SPawel Dembicki 	 */
93395711cd5SPawel Dembicki 	vsc73xx_write(vsc, VSC73XX_BLOCK_MAC,
93495711cd5SPawel Dembicki 		      port,
93595711cd5SPawel Dembicki 		      VSC73XX_CAT_DROP,
93695711cd5SPawel Dembicki 		      VSC73XX_CAT_DROP_FWD_PAUSE_ENA);
93795711cd5SPawel Dembicki 
93895711cd5SPawel Dembicki 	/* Clear all counters */
93995711cd5SPawel Dembicki 	vsc73xx_write(vsc, VSC73XX_BLOCK_MAC,
94095711cd5SPawel Dembicki 		      port, VSC73XX_C_RX0, 0);
94195711cd5SPawel Dembicki }
94295711cd5SPawel Dembicki 
94321fc3416SPawel Dembicki static void vsc73xx_reset_port(struct vsc73xx *vsc, int port, u32 initval)
94495711cd5SPawel Dembicki {
945eb7e33d0SPawel Dembicki 	int ret, err;
94621fc3416SPawel Dembicki 	u32 val;
94795711cd5SPawel Dembicki 
94895711cd5SPawel Dembicki 	/* Disable RX on this port */
94995711cd5SPawel Dembicki 	vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port,
95095711cd5SPawel Dembicki 			    VSC73XX_MAC_CFG,
95195711cd5SPawel Dembicki 			    VSC73XX_MAC_CFG_RX_EN, 0);
95295711cd5SPawel Dembicki 
95395711cd5SPawel Dembicki 	/* Discard packets */
95495711cd5SPawel Dembicki 	vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, 0,
95595711cd5SPawel Dembicki 			    VSC73XX_ARBDISC, BIT(port), BIT(port));
95695711cd5SPawel Dembicki 
95795711cd5SPawel Dembicki 	/* Wait until queue is empty */
958eb7e33d0SPawel Dembicki 	ret = read_poll_timeout(vsc73xx_read, err,
959eb7e33d0SPawel Dembicki 				err < 0 || (val & BIT(port)),
960eb7e33d0SPawel Dembicki 				VSC73XX_POLL_SLEEP_US,
961eb7e33d0SPawel Dembicki 				VSC73XX_POLL_TIMEOUT_US, false,
962eb7e33d0SPawel Dembicki 				vsc, VSC73XX_BLOCK_ARBITER, 0,
96395711cd5SPawel Dembicki 				VSC73XX_ARBEMPTY, &val);
964eb7e33d0SPawel Dembicki 	if (ret)
96595711cd5SPawel Dembicki 		dev_err(vsc->dev,
96695711cd5SPawel Dembicki 			"timeout waiting for block arbiter\n");
967eb7e33d0SPawel Dembicki 	else if (err < 0)
968eb7e33d0SPawel Dembicki 		dev_err(vsc->dev, "error reading arbiter\n");
96995711cd5SPawel Dembicki 
97095711cd5SPawel Dembicki 	/* Put this port into reset */
97195711cd5SPawel Dembicki 	vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, VSC73XX_MAC_CFG,
97221fc3416SPawel Dembicki 		      VSC73XX_MAC_CFG_RESET | initval);
97321fc3416SPawel Dembicki }
97495711cd5SPawel Dembicki 
97521fc3416SPawel Dembicki static void vsc73xx_mac_config(struct phylink_config *config, unsigned int mode,
97621fc3416SPawel Dembicki 			       const struct phylink_link_state *state)
97721fc3416SPawel Dembicki {
97821fc3416SPawel Dembicki 	struct dsa_port *dp = dsa_phylink_to_port(config);
97921fc3416SPawel Dembicki 	struct vsc73xx *vsc = dp->ds->priv;
98021fc3416SPawel Dembicki 	int port = dp->index;
98121fc3416SPawel Dembicki 
98221fc3416SPawel Dembicki 	/* Special handling of the CPU-facing port */
98321fc3416SPawel Dembicki 	if (port == CPU_PORT) {
98421fc3416SPawel Dembicki 		/* Other ports are already initialized but not this one */
98521fc3416SPawel Dembicki 		vsc73xx_init_port(vsc, CPU_PORT);
98621fc3416SPawel Dembicki 		/* Select the external port for this interface (EXT_PORT)
98721fc3416SPawel Dembicki 		 * Enable the GMII GTX external clock
98821fc3416SPawel Dembicki 		 * Use double data rate (DDR mode)
98921fc3416SPawel Dembicki 		 */
99021fc3416SPawel Dembicki 		vsc73xx_write(vsc, VSC73XX_BLOCK_MAC,
99121fc3416SPawel Dembicki 			      CPU_PORT,
99221fc3416SPawel Dembicki 			      VSC73XX_ADVPORTM,
99321fc3416SPawel Dembicki 			      VSC73XX_ADVPORTM_EXT_PORT |
99421fc3416SPawel Dembicki 			      VSC73XX_ADVPORTM_ENA_GTX |
99521fc3416SPawel Dembicki 			      VSC73XX_ADVPORTM_DDR_MODE);
99621fc3416SPawel Dembicki 	}
99721fc3416SPawel Dembicki }
99821fc3416SPawel Dembicki 
99921fc3416SPawel Dembicki static void vsc73xx_mac_link_down(struct phylink_config *config,
100021fc3416SPawel Dembicki 				  unsigned int mode, phy_interface_t interface)
100121fc3416SPawel Dembicki {
100221fc3416SPawel Dembicki 	struct dsa_port *dp = dsa_phylink_to_port(config);
100321fc3416SPawel Dembicki 	struct vsc73xx *vsc = dp->ds->priv;
100421fc3416SPawel Dembicki 	int port = dp->index;
100521fc3416SPawel Dembicki 
100621fc3416SPawel Dembicki 	/* This routine is described in the datasheet (below ARBDISC register
100721fc3416SPawel Dembicki 	 * description)
100821fc3416SPawel Dembicki 	 */
100921fc3416SPawel Dembicki 	vsc73xx_reset_port(vsc, port, 0);
101095711cd5SPawel Dembicki 
101195711cd5SPawel Dembicki 	/* Allow backward dropping of frames from this port */
101295711cd5SPawel Dembicki 	vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, 0,
101395711cd5SPawel Dembicki 			    VSC73XX_SBACKWDROP, BIT(port), BIT(port));
101495711cd5SPawel Dembicki }
101595711cd5SPawel Dembicki 
101621fc3416SPawel Dembicki static void vsc73xx_mac_link_up(struct phylink_config *config,
101721fc3416SPawel Dembicki 				struct phy_device *phy, unsigned int mode,
101821fc3416SPawel Dembicki 				phy_interface_t interface, int speed,
101921fc3416SPawel Dembicki 				int duplex, bool tx_pause, bool rx_pause)
102021fc3416SPawel Dembicki {
102121fc3416SPawel Dembicki 	struct dsa_port *dp = dsa_phylink_to_port(config);
102221fc3416SPawel Dembicki 	struct vsc73xx *vsc = dp->ds->priv;
102321fc3416SPawel Dembicki 	int port = dp->index;
102421fc3416SPawel Dembicki 	u32 val;
102521fc3416SPawel Dembicki 	u8 seed;
102695711cd5SPawel Dembicki 
102721fc3416SPawel Dembicki 	if (speed == SPEED_1000)
102821fc3416SPawel Dembicki 		val = VSC73XX_MAC_CFG_GIGA_MODE | VSC73XX_MAC_CFG_TX_IPG_1000M;
102995711cd5SPawel Dembicki 	else
103021fc3416SPawel Dembicki 		val = VSC73XX_MAC_CFG_TX_IPG_100_10M;
103195711cd5SPawel Dembicki 
103212af94b2SPawel Dembicki 	if (phy_interface_mode_is_rgmii(interface))
103321fc3416SPawel Dembicki 		val |= VSC73XX_MAC_CFG_CLK_SEL_1000M;
103421fc3416SPawel Dembicki 	else
103521fc3416SPawel Dembicki 		val |= VSC73XX_MAC_CFG_CLK_SEL_EXT;
103621fc3416SPawel Dembicki 
103721fc3416SPawel Dembicki 	if (duplex == DUPLEX_FULL)
103821fc3416SPawel Dembicki 		val |= VSC73XX_MAC_CFG_FDX;
103921fc3416SPawel Dembicki 
104021fc3416SPawel Dembicki 	/* This routine is described in the datasheet (below ARBDISC register
104121fc3416SPawel Dembicki 	 * description)
104221fc3416SPawel Dembicki 	 */
104321fc3416SPawel Dembicki 	vsc73xx_reset_port(vsc, port, val);
104421fc3416SPawel Dembicki 
104521fc3416SPawel Dembicki 	/* Seed the port randomness with randomness */
104621fc3416SPawel Dembicki 	get_random_bytes(&seed, 1);
104721fc3416SPawel Dembicki 	val |= seed << VSC73XX_MAC_CFG_SEED_OFFSET;
104821fc3416SPawel Dembicki 	val |= VSC73XX_MAC_CFG_SEED_LOAD;
104921fc3416SPawel Dembicki 	val |= VSC73XX_MAC_CFG_WEXC_DIS;
10506b783dedSPawel Dembicki 
10516b783dedSPawel Dembicki 	/* Those bits are responsible for MTU only. Kernel takes care about MTU,
10526b783dedSPawel Dembicki 	 * let's enable +8 bytes frame length unconditionally.
10536b783dedSPawel Dembicki 	 */
10546b783dedSPawel Dembicki 	val |= VSC73XX_MAC_CFG_VLAN_AWR | VSC73XX_MAC_CFG_VLAN_DBLAWR;
10556b783dedSPawel Dembicki 
105621fc3416SPawel Dembicki 	vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, VSC73XX_MAC_CFG, val);
105721fc3416SPawel Dembicki 
105821fc3416SPawel Dembicki 	/* Flow control for the PHY facing ports:
105921fc3416SPawel Dembicki 	 * Use a zero delay pause frame when pause condition is left
106021fc3416SPawel Dembicki 	 * Obey pause control frames
106121fc3416SPawel Dembicki 	 * When generating pause frames, use 0xff as pause value
106221fc3416SPawel Dembicki 	 */
106321fc3416SPawel Dembicki 	vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, VSC73XX_FCCONF,
106421fc3416SPawel Dembicki 		      VSC73XX_FCCONF_ZERO_PAUSE_EN |
106521fc3416SPawel Dembicki 		      VSC73XX_FCCONF_FLOW_CTRL_OBEY |
106621fc3416SPawel Dembicki 		      0xff);
106721fc3416SPawel Dembicki 
106821fc3416SPawel Dembicki 	/* Accept packets again */
106921fc3416SPawel Dembicki 	vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, 0,
107021fc3416SPawel Dembicki 			    VSC73XX_ARBDISC, BIT(port), 0);
107121fc3416SPawel Dembicki 
107221fc3416SPawel Dembicki 	/* Disallow backward dropping of frames from this port */
107321fc3416SPawel Dembicki 	vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, 0,
107421fc3416SPawel Dembicki 			    VSC73XX_SBACKWDROP, BIT(port), 0);
107521fc3416SPawel Dembicki 
107621fc3416SPawel Dembicki 	/* Enable TX, RX, deassert reset, stop loading seed */
107721fc3416SPawel Dembicki 	vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port,
107821fc3416SPawel Dembicki 			    VSC73XX_MAC_CFG,
107921fc3416SPawel Dembicki 			    VSC73XX_MAC_CFG_RESET | VSC73XX_MAC_CFG_SEED_LOAD |
108021fc3416SPawel Dembicki 			    VSC73XX_MAC_CFG_TX_EN | VSC73XX_MAC_CFG_RX_EN,
108121fc3416SPawel Dembicki 			    VSC73XX_MAC_CFG_TX_EN | VSC73XX_MAC_CFG_RX_EN);
108295711cd5SPawel Dembicki }
108395711cd5SPawel Dembicki 
10846b783dedSPawel Dembicki static bool vsc73xx_tag_8021q_active(struct dsa_port *dp)
10856b783dedSPawel Dembicki {
10866b783dedSPawel Dembicki 	return !dsa_port_is_vlan_filtering(dp);
10876b783dedSPawel Dembicki }
10886b783dedSPawel Dembicki 
10896b783dedSPawel Dembicki static struct vsc73xx_bridge_vlan *
10906b783dedSPawel Dembicki vsc73xx_bridge_vlan_find(struct vsc73xx *vsc, u16 vid)
10916b783dedSPawel Dembicki {
10926b783dedSPawel Dembicki 	struct vsc73xx_bridge_vlan *vlan;
10936b783dedSPawel Dembicki 
10946b783dedSPawel Dembicki 	list_for_each_entry(vlan, &vsc->vlans, list)
10956b783dedSPawel Dembicki 		if (vlan->vid == vid)
10966b783dedSPawel Dembicki 			return vlan;
10976b783dedSPawel Dembicki 
10986b783dedSPawel Dembicki 	return NULL;
10996b783dedSPawel Dembicki }
11006b783dedSPawel Dembicki 
11016b783dedSPawel Dembicki static void
11026b783dedSPawel Dembicki vsc73xx_bridge_vlan_remove_port(struct vsc73xx_bridge_vlan *vsc73xx_vlan,
11036b783dedSPawel Dembicki 				int port)
11046b783dedSPawel Dembicki {
11056b783dedSPawel Dembicki 	vsc73xx_vlan->portmask &= ~BIT(port);
11066b783dedSPawel Dembicki 
11076b783dedSPawel Dembicki 	if (vsc73xx_vlan->portmask)
11086b783dedSPawel Dembicki 		return;
11096b783dedSPawel Dembicki 
11106b783dedSPawel Dembicki 	list_del(&vsc73xx_vlan->list);
11116b783dedSPawel Dembicki 	kfree(vsc73xx_vlan);
11126b783dedSPawel Dembicki }
11136b783dedSPawel Dembicki 
11146b783dedSPawel Dembicki static void vsc73xx_bridge_vlan_summary(struct vsc73xx *vsc, int port,
11156b783dedSPawel Dembicki 					struct vsc73xx_vlan_summary *summary,
11166b783dedSPawel Dembicki 					u16 ignored_vid)
11176b783dedSPawel Dembicki {
11186b783dedSPawel Dembicki 	size_t num_tagged = 0, num_untagged = 0;
11196b783dedSPawel Dembicki 	struct vsc73xx_bridge_vlan *vlan;
11206b783dedSPawel Dembicki 
11216b783dedSPawel Dembicki 	list_for_each_entry(vlan, &vsc->vlans, list) {
11226b783dedSPawel Dembicki 		if (!(vlan->portmask & BIT(port)) || vlan->vid == ignored_vid)
11236b783dedSPawel Dembicki 			continue;
11246b783dedSPawel Dembicki 
11256b783dedSPawel Dembicki 		if (vlan->untagged & BIT(port))
11266b783dedSPawel Dembicki 			num_untagged++;
11276b783dedSPawel Dembicki 		else
11286b783dedSPawel Dembicki 			num_tagged++;
11296b783dedSPawel Dembicki 	}
11306b783dedSPawel Dembicki 
11316b783dedSPawel Dembicki 	summary->num_untagged = num_untagged;
11326b783dedSPawel Dembicki 	summary->num_tagged = num_tagged;
11336b783dedSPawel Dembicki }
11346b783dedSPawel Dembicki 
11356b783dedSPawel Dembicki static u16 vsc73xx_find_first_vlan_untagged(struct vsc73xx *vsc, int port)
11366b783dedSPawel Dembicki {
11376b783dedSPawel Dembicki 	struct vsc73xx_bridge_vlan *vlan;
11386b783dedSPawel Dembicki 
11396b783dedSPawel Dembicki 	list_for_each_entry(vlan, &vsc->vlans, list)
11406b783dedSPawel Dembicki 		if ((vlan->portmask & BIT(port)) &&
11416b783dedSPawel Dembicki 		    (vlan->untagged & BIT(port)))
11426b783dedSPawel Dembicki 			return vlan->vid;
11436b783dedSPawel Dembicki 
11446b783dedSPawel Dembicki 	return VLAN_N_VID;
11456b783dedSPawel Dembicki }
11466b783dedSPawel Dembicki 
11476b783dedSPawel Dembicki static int vsc73xx_set_vlan_conf(struct vsc73xx *vsc, int port,
11486b783dedSPawel Dembicki 				 enum vsc73xx_port_vlan_conf port_vlan_conf)
11496b783dedSPawel Dembicki {
11506b783dedSPawel Dembicki 	u32 val = 0;
11516b783dedSPawel Dembicki 	int ret;
11526b783dedSPawel Dembicki 
11536b783dedSPawel Dembicki 	if (port_vlan_conf == VSC73XX_VLAN_IGNORE)
11546b783dedSPawel Dembicki 		val = VSC73XX_CAT_VLAN_MISC_VLAN_TCI_IGNORE_ENA |
11556b783dedSPawel Dembicki 		      VSC73XX_CAT_VLAN_MISC_VLAN_KEEP_TAG_ENA;
11566b783dedSPawel Dembicki 
11576b783dedSPawel Dembicki 	ret = vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port,
11586b783dedSPawel Dembicki 				  VSC73XX_CAT_VLAN_MISC,
11596b783dedSPawel Dembicki 				  VSC73XX_CAT_VLAN_MISC_VLAN_TCI_IGNORE_ENA |
11606b783dedSPawel Dembicki 				  VSC73XX_CAT_VLAN_MISC_VLAN_KEEP_TAG_ENA, val);
11616b783dedSPawel Dembicki 	if (ret)
11626b783dedSPawel Dembicki 		return ret;
11636b783dedSPawel Dembicki 
11646b783dedSPawel Dembicki 	val = (port_vlan_conf == VSC73XX_VLAN_FILTER) ?
11656b783dedSPawel Dembicki 	      VSC73XX_TXUPDCFG_TX_INSERT_TAG : 0;
11666b783dedSPawel Dembicki 
11676b783dedSPawel Dembicki 	return vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port,
11686b783dedSPawel Dembicki 				   VSC73XX_TXUPDCFG,
11696b783dedSPawel Dembicki 				   VSC73XX_TXUPDCFG_TX_INSERT_TAG, val);
11706b783dedSPawel Dembicki }
11716b783dedSPawel Dembicki 
11726b783dedSPawel Dembicki /**
11736b783dedSPawel Dembicki  * vsc73xx_vlan_commit_conf - Update VLAN configuration of a port
11746b783dedSPawel Dembicki  * @vsc: Switch private data structure
11756b783dedSPawel Dembicki  * @port: Port index on which to operate
11766b783dedSPawel Dembicki  *
11776b783dedSPawel Dembicki  * Update the VLAN behavior of a port to make sure that when it is under
11786b783dedSPawel Dembicki  * a VLAN filtering bridge, the port is either filtering with tag
11796b783dedSPawel Dembicki  * preservation, or filtering with all VLANs egress-untagged. Otherwise,
11806b783dedSPawel Dembicki  * the port ignores VLAN tags from packets and applies the port-based
11816b783dedSPawel Dembicki  * VID.
11826b783dedSPawel Dembicki  *
11836b783dedSPawel Dembicki  * Must be called when changes are made to:
11846b783dedSPawel Dembicki  * - the bridge VLAN filtering state of the port
11856b783dedSPawel Dembicki  * - the number or attributes of VLANs from the bridge VLAN table,
11866b783dedSPawel Dembicki  *   while the port is currently VLAN-aware
11876b783dedSPawel Dembicki  *
11886b783dedSPawel Dembicki  * Return: 0 on success, or negative errno on error.
11896b783dedSPawel Dembicki  */
11906b783dedSPawel Dembicki static int vsc73xx_vlan_commit_conf(struct vsc73xx *vsc, int port)
11916b783dedSPawel Dembicki {
11926b783dedSPawel Dembicki 	enum vsc73xx_port_vlan_conf port_vlan_conf = VSC73XX_VLAN_IGNORE;
11936b783dedSPawel Dembicki 	struct dsa_port *dp = dsa_to_port(vsc->ds, port);
11946b783dedSPawel Dembicki 
11956b783dedSPawel Dembicki 	if (port == CPU_PORT) {
11966b783dedSPawel Dembicki 		port_vlan_conf = VSC73XX_VLAN_FILTER;
11976b783dedSPawel Dembicki 	} else if (dsa_port_is_vlan_filtering(dp)) {
11986b783dedSPawel Dembicki 		struct vsc73xx_vlan_summary summary;
11996b783dedSPawel Dembicki 
12006b783dedSPawel Dembicki 		port_vlan_conf = VSC73XX_VLAN_FILTER;
12016b783dedSPawel Dembicki 
12026b783dedSPawel Dembicki 		vsc73xx_bridge_vlan_summary(vsc, port, &summary, VLAN_N_VID);
12036b783dedSPawel Dembicki 		if (summary.num_tagged == 0)
12046b783dedSPawel Dembicki 			port_vlan_conf = VSC73XX_VLAN_FILTER_UNTAG_ALL;
12056b783dedSPawel Dembicki 	}
12066b783dedSPawel Dembicki 
12076b783dedSPawel Dembicki 	return vsc73xx_set_vlan_conf(vsc, port, port_vlan_conf);
12086b783dedSPawel Dembicki }
12096b783dedSPawel Dembicki 
12106b783dedSPawel Dembicki static int
12116b783dedSPawel Dembicki vsc73xx_vlan_change_untagged(struct vsc73xx *vsc, int port, u16 vid, bool set)
12126b783dedSPawel Dembicki {
12136b783dedSPawel Dembicki 	u32 val = 0;
12146b783dedSPawel Dembicki 
12156b783dedSPawel Dembicki 	if (set)
12166b783dedSPawel Dembicki 		val = VSC73XX_TXUPDCFG_TX_UNTAGGED_VID_ENA |
12176b783dedSPawel Dembicki 		      ((vid << VSC73XX_TXUPDCFG_TX_UNTAGGED_VID_SHIFT) &
12186b783dedSPawel Dembicki 		       VSC73XX_TXUPDCFG_TX_UNTAGGED_VID);
12196b783dedSPawel Dembicki 
12206b783dedSPawel Dembicki 	return vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port,
12216b783dedSPawel Dembicki 				   VSC73XX_TXUPDCFG,
12226b783dedSPawel Dembicki 				   VSC73XX_TXUPDCFG_TX_UNTAGGED_VID_ENA |
12236b783dedSPawel Dembicki 				   VSC73XX_TXUPDCFG_TX_UNTAGGED_VID, val);
12246b783dedSPawel Dembicki }
12256b783dedSPawel Dembicki 
12266b783dedSPawel Dembicki /**
12276b783dedSPawel Dembicki  * vsc73xx_vlan_commit_untagged - Update native VLAN of a port
12286b783dedSPawel Dembicki  * @vsc: Switch private data structure
12296b783dedSPawel Dembicki  * @port: Port index on which to operate
12306b783dedSPawel Dembicki  *
12316b783dedSPawel Dembicki  * Update the native VLAN of a port (the one VLAN which is transmitted
12326b783dedSPawel Dembicki  * as egress-tagged on a trunk port) when port is in VLAN filtering mode and
12336b783dedSPawel Dembicki  * only one untagged vid is configured.
12346b783dedSPawel Dembicki  * In other cases no need to configure it because switch can untag all vlans on
12356b783dedSPawel Dembicki  * the port.
12366b783dedSPawel Dembicki  *
12376b783dedSPawel Dembicki  * Return: 0 on success, or negative errno on error.
12386b783dedSPawel Dembicki  */
12396b783dedSPawel Dembicki static int vsc73xx_vlan_commit_untagged(struct vsc73xx *vsc, int port)
12406b783dedSPawel Dembicki {
12416b783dedSPawel Dembicki 	struct dsa_port *dp = dsa_to_port(vsc->ds, port);
12426b783dedSPawel Dembicki 	struct vsc73xx_vlan_summary summary;
12436b783dedSPawel Dembicki 	u16 vid = 0;
12446b783dedSPawel Dembicki 	bool valid;
12456b783dedSPawel Dembicki 
12466b783dedSPawel Dembicki 	if (!dsa_port_is_vlan_filtering(dp))
12476b783dedSPawel Dembicki 		/* Port is configured to untag all vlans in that case.
12486b783dedSPawel Dembicki 		 * No need to commit untagged config change.
12496b783dedSPawel Dembicki 		 */
12506b783dedSPawel Dembicki 		return 0;
12516b783dedSPawel Dembicki 
12526b783dedSPawel Dembicki 	vsc73xx_bridge_vlan_summary(vsc, port, &summary, VLAN_N_VID);
12536b783dedSPawel Dembicki 
12546b783dedSPawel Dembicki 	if (summary.num_untagged > 1)
12556b783dedSPawel Dembicki 		/* Port must untag all vlans in that case.
12566b783dedSPawel Dembicki 		 * No need to commit untagged config change.
12576b783dedSPawel Dembicki 		 */
12586b783dedSPawel Dembicki 		return 0;
12596b783dedSPawel Dembicki 
12606b783dedSPawel Dembicki 	valid = (summary.num_untagged == 1);
12616b783dedSPawel Dembicki 	if (valid)
12626b783dedSPawel Dembicki 		vid = vsc73xx_find_first_vlan_untagged(vsc, port);
12636b783dedSPawel Dembicki 
12646b783dedSPawel Dembicki 	return vsc73xx_vlan_change_untagged(vsc, port, vid, valid);
12656b783dedSPawel Dembicki }
12666b783dedSPawel Dembicki 
12676b783dedSPawel Dembicki static int
12686b783dedSPawel Dembicki vsc73xx_vlan_change_pvid(struct vsc73xx *vsc, int port, u16 vid, bool set)
12696b783dedSPawel Dembicki {
12706b783dedSPawel Dembicki 	u32 val = 0;
12716b783dedSPawel Dembicki 	int ret;
12726b783dedSPawel Dembicki 
12736b783dedSPawel Dembicki 	val = set ? 0 : VSC73XX_CAT_DROP_UNTAGGED_ENA;
12746b783dedSPawel Dembicki 
12756b783dedSPawel Dembicki 	ret = vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port,
12766b783dedSPawel Dembicki 				  VSC73XX_CAT_DROP,
12776b783dedSPawel Dembicki 				  VSC73XX_CAT_DROP_UNTAGGED_ENA, val);
12786b783dedSPawel Dembicki 	if (!set || ret)
12796b783dedSPawel Dembicki 		return ret;
12806b783dedSPawel Dembicki 
12816b783dedSPawel Dembicki 	return vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port,
12826b783dedSPawel Dembicki 				   VSC73XX_CAT_PORT_VLAN,
12836b783dedSPawel Dembicki 				   VSC73XX_CAT_PORT_VLAN_VLAN_VID,
12846b783dedSPawel Dembicki 				   vid & VSC73XX_CAT_PORT_VLAN_VLAN_VID);
12856b783dedSPawel Dembicki }
12866b783dedSPawel Dembicki 
12876b783dedSPawel Dembicki /**
12886b783dedSPawel Dembicki  * vsc73xx_vlan_commit_pvid - Update port-based default VLAN of a port
12896b783dedSPawel Dembicki  * @vsc: Switch private data structure
12906b783dedSPawel Dembicki  * @port: Port index on which to operate
12916b783dedSPawel Dembicki  *
12926b783dedSPawel Dembicki  * Update the PVID of a port so that it follows either the bridge PVID
12936b783dedSPawel Dembicki  * configuration, when the bridge is currently VLAN-aware, or the PVID
12946b783dedSPawel Dembicki  * from tag_8021q, when the port is standalone or under a VLAN-unaware
12956b783dedSPawel Dembicki  * bridge. A port with no PVID drops all untagged and VID 0 tagged
12966b783dedSPawel Dembicki  * traffic.
12976b783dedSPawel Dembicki  *
12986b783dedSPawel Dembicki  * Must be called when changes are made to:
12996b783dedSPawel Dembicki  * - the bridge VLAN filtering state of the port
13006b783dedSPawel Dembicki  * - the number or attributes of VLANs from the bridge VLAN table,
13016b783dedSPawel Dembicki  *   while the port is currently VLAN-aware
13026b783dedSPawel Dembicki  *
13036b783dedSPawel Dembicki  * Return: 0 on success, or negative errno on error.
13046b783dedSPawel Dembicki  */
13056b783dedSPawel Dembicki static int vsc73xx_vlan_commit_pvid(struct vsc73xx *vsc, int port)
13066b783dedSPawel Dembicki {
13076b783dedSPawel Dembicki 	struct vsc73xx_portinfo *portinfo = &vsc->portinfo[port];
13086b783dedSPawel Dembicki 	bool valid = portinfo->pvid_tag_8021q_configured;
13096b783dedSPawel Dembicki 	struct dsa_port *dp = dsa_to_port(vsc->ds, port);
13106b783dedSPawel Dembicki 	u16 vid = portinfo->pvid_tag_8021q;
13116b783dedSPawel Dembicki 
13126b783dedSPawel Dembicki 	if (dsa_port_is_vlan_filtering(dp)) {
13136b783dedSPawel Dembicki 		vid = portinfo->pvid_vlan_filtering;
13146b783dedSPawel Dembicki 		valid = portinfo->pvid_vlan_filtering_configured;
13156b783dedSPawel Dembicki 	}
13166b783dedSPawel Dembicki 
13176b783dedSPawel Dembicki 	return vsc73xx_vlan_change_pvid(vsc, port, vid, valid);
13186b783dedSPawel Dembicki }
13196b783dedSPawel Dembicki 
13206b783dedSPawel Dembicki static int vsc73xx_vlan_commit_settings(struct vsc73xx *vsc, int port)
13216b783dedSPawel Dembicki {
13226b783dedSPawel Dembicki 	int ret;
13236b783dedSPawel Dembicki 
13246b783dedSPawel Dembicki 	ret = vsc73xx_vlan_commit_untagged(vsc, port);
13256b783dedSPawel Dembicki 	if (ret)
13266b783dedSPawel Dembicki 		return ret;
13276b783dedSPawel Dembicki 
13286b783dedSPawel Dembicki 	ret = vsc73xx_vlan_commit_pvid(vsc, port);
13296b783dedSPawel Dembicki 	if (ret)
13306b783dedSPawel Dembicki 		return ret;
13316b783dedSPawel Dembicki 
13326b783dedSPawel Dembicki 	return vsc73xx_vlan_commit_conf(vsc, port);
13336b783dedSPawel Dembicki }
13346b783dedSPawel Dembicki 
133595711cd5SPawel Dembicki static int vsc73xx_port_enable(struct dsa_switch *ds, int port,
133695711cd5SPawel Dembicki 			       struct phy_device *phy)
133795711cd5SPawel Dembicki {
133895711cd5SPawel Dembicki 	struct vsc73xx *vsc = ds->priv;
133995711cd5SPawel Dembicki 
134095711cd5SPawel Dembicki 	dev_info(vsc->dev, "enable port %d\n", port);
134195711cd5SPawel Dembicki 	vsc73xx_init_port(vsc, port);
134295711cd5SPawel Dembicki 
13436b783dedSPawel Dembicki 	return vsc73xx_vlan_commit_settings(vsc, port);
134495711cd5SPawel Dembicki }
134595711cd5SPawel Dembicki 
134695711cd5SPawel Dembicki static void vsc73xx_port_disable(struct dsa_switch *ds, int port)
134795711cd5SPawel Dembicki {
134895711cd5SPawel Dembicki 	struct vsc73xx *vsc = ds->priv;
134995711cd5SPawel Dembicki 
135095711cd5SPawel Dembicki 	/* Just put the port into reset */
135195711cd5SPawel Dembicki 	vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port,
135295711cd5SPawel Dembicki 		      VSC73XX_MAC_CFG, VSC73XX_MAC_CFG_RESET);
135395711cd5SPawel Dembicki }
135495711cd5SPawel Dembicki 
135595711cd5SPawel Dembicki static const struct vsc73xx_counter *
135695711cd5SPawel Dembicki vsc73xx_find_counter(struct vsc73xx *vsc,
135795711cd5SPawel Dembicki 		     u8 counter,
135895711cd5SPawel Dembicki 		     bool tx)
135995711cd5SPawel Dembicki {
136095711cd5SPawel Dembicki 	const struct vsc73xx_counter *cnts;
136195711cd5SPawel Dembicki 	int num_cnts;
136295711cd5SPawel Dembicki 	int i;
136395711cd5SPawel Dembicki 
136495711cd5SPawel Dembicki 	if (tx) {
136595711cd5SPawel Dembicki 		cnts = vsc73xx_tx_counters;
136695711cd5SPawel Dembicki 		num_cnts = ARRAY_SIZE(vsc73xx_tx_counters);
136795711cd5SPawel Dembicki 	} else {
136895711cd5SPawel Dembicki 		cnts = vsc73xx_rx_counters;
136995711cd5SPawel Dembicki 		num_cnts = ARRAY_SIZE(vsc73xx_rx_counters);
137095711cd5SPawel Dembicki 	}
137195711cd5SPawel Dembicki 
137295711cd5SPawel Dembicki 	for (i = 0; i < num_cnts; i++) {
137395711cd5SPawel Dembicki 		const struct vsc73xx_counter *cnt;
137495711cd5SPawel Dembicki 
137595711cd5SPawel Dembicki 		cnt = &cnts[i];
137695711cd5SPawel Dembicki 		if (cnt->counter == counter)
137795711cd5SPawel Dembicki 			return cnt;
137895711cd5SPawel Dembicki 	}
137995711cd5SPawel Dembicki 
138095711cd5SPawel Dembicki 	return NULL;
138195711cd5SPawel Dembicki }
138295711cd5SPawel Dembicki 
138395711cd5SPawel Dembicki static void vsc73xx_get_strings(struct dsa_switch *ds, int port, u32 stringset,
138495711cd5SPawel Dembicki 				uint8_t *data)
138595711cd5SPawel Dembicki {
138695711cd5SPawel Dembicki 	const struct vsc73xx_counter *cnt;
138795711cd5SPawel Dembicki 	struct vsc73xx *vsc = ds->priv;
138895711cd5SPawel Dembicki 	u8 indices[6];
1389e3bbab47SJustin Stitt 	u8 *buf = data;
1390e3bbab47SJustin Stitt 	int i;
139195711cd5SPawel Dembicki 	u32 val;
139295711cd5SPawel Dembicki 	int ret;
139395711cd5SPawel Dembicki 
139495711cd5SPawel Dembicki 	if (stringset != ETH_SS_STATS)
139595711cd5SPawel Dembicki 		return;
139695711cd5SPawel Dembicki 
139795711cd5SPawel Dembicki 	ret = vsc73xx_read(vsc, VSC73XX_BLOCK_MAC, port,
139895711cd5SPawel Dembicki 			   VSC73XX_C_CFG, &val);
139995711cd5SPawel Dembicki 	if (ret)
140095711cd5SPawel Dembicki 		return;
140195711cd5SPawel Dembicki 
140295711cd5SPawel Dembicki 	indices[0] = (val & 0x1f); /* RX counter 0 */
140395711cd5SPawel Dembicki 	indices[1] = ((val >> 5) & 0x1f); /* RX counter 1 */
140495711cd5SPawel Dembicki 	indices[2] = ((val >> 10) & 0x1f); /* RX counter 2 */
140595711cd5SPawel Dembicki 	indices[3] = ((val >> 16) & 0x1f); /* TX counter 0 */
140695711cd5SPawel Dembicki 	indices[4] = ((val >> 21) & 0x1f); /* TX counter 1 */
140795711cd5SPawel Dembicki 	indices[5] = ((val >> 26) & 0x1f); /* TX counter 2 */
140895711cd5SPawel Dembicki 
140995711cd5SPawel Dembicki 	/* The first counters is the RX octets */
1410e403cfffSjustinstitt@google.com 	ethtool_puts(&buf, "RxEtherStatsOctets");
141195711cd5SPawel Dembicki 
141295711cd5SPawel Dembicki 	/* Each port supports recording 3 RX counters and 3 TX counters,
141395711cd5SPawel Dembicki 	 * figure out what counters we use in this set-up and return the
141495711cd5SPawel Dembicki 	 * names of them. The hardware default counters will be number of
141595711cd5SPawel Dembicki 	 * packets on RX/TX, combined broadcast+multicast packets RX/TX and
141695711cd5SPawel Dembicki 	 * total error packets RX/TX.
141795711cd5SPawel Dembicki 	 */
141895711cd5SPawel Dembicki 	for (i = 0; i < 3; i++) {
141995711cd5SPawel Dembicki 		cnt = vsc73xx_find_counter(vsc, indices[i], false);
1420e403cfffSjustinstitt@google.com 		ethtool_puts(&buf, cnt ? cnt->name : "");
142195711cd5SPawel Dembicki 	}
142295711cd5SPawel Dembicki 
142395711cd5SPawel Dembicki 	/* TX stats begins with the number of TX octets */
1424e403cfffSjustinstitt@google.com 	ethtool_puts(&buf, "TxEtherStatsOctets");
142595711cd5SPawel Dembicki 
142695711cd5SPawel Dembicki 	for (i = 3; i < 6; i++) {
142795711cd5SPawel Dembicki 		cnt = vsc73xx_find_counter(vsc, indices[i], true);
1428e403cfffSjustinstitt@google.com 		ethtool_puts(&buf, cnt ? cnt->name : "");
1429e3bbab47SJustin Stitt 
143095711cd5SPawel Dembicki 	}
143195711cd5SPawel Dembicki }
143295711cd5SPawel Dembicki 
143395711cd5SPawel Dembicki static int vsc73xx_get_sset_count(struct dsa_switch *ds, int port, int sset)
143495711cd5SPawel Dembicki {
143595711cd5SPawel Dembicki 	/* We only support SS_STATS */
143695711cd5SPawel Dembicki 	if (sset != ETH_SS_STATS)
143795711cd5SPawel Dembicki 		return 0;
143895711cd5SPawel Dembicki 	/* RX and TX packets, then 3 RX counters, 3 TX counters */
143995711cd5SPawel Dembicki 	return 8;
144095711cd5SPawel Dembicki }
144195711cd5SPawel Dembicki 
144295711cd5SPawel Dembicki static void vsc73xx_get_ethtool_stats(struct dsa_switch *ds, int port,
144395711cd5SPawel Dembicki 				      uint64_t *data)
144495711cd5SPawel Dembicki {
144595711cd5SPawel Dembicki 	struct vsc73xx *vsc = ds->priv;
144695711cd5SPawel Dembicki 	u8 regs[] = {
144795711cd5SPawel Dembicki 		VSC73XX_RXOCT,
144895711cd5SPawel Dembicki 		VSC73XX_C_RX0,
144995711cd5SPawel Dembicki 		VSC73XX_C_RX1,
145095711cd5SPawel Dembicki 		VSC73XX_C_RX2,
145195711cd5SPawel Dembicki 		VSC73XX_TXOCT,
145295711cd5SPawel Dembicki 		VSC73XX_C_TX0,
145395711cd5SPawel Dembicki 		VSC73XX_C_TX1,
145495711cd5SPawel Dembicki 		VSC73XX_C_TX2,
145595711cd5SPawel Dembicki 	};
145695711cd5SPawel Dembicki 	u32 val;
145795711cd5SPawel Dembicki 	int ret;
145895711cd5SPawel Dembicki 	int i;
145995711cd5SPawel Dembicki 
146095711cd5SPawel Dembicki 	for (i = 0; i < ARRAY_SIZE(regs); i++) {
146195711cd5SPawel Dembicki 		ret = vsc73xx_read(vsc, VSC73XX_BLOCK_MAC, port,
146295711cd5SPawel Dembicki 				   regs[i], &val);
146395711cd5SPawel Dembicki 		if (ret) {
146495711cd5SPawel Dembicki 			dev_err(vsc->dev, "error reading counter %d\n", i);
146595711cd5SPawel Dembicki 			return;
146695711cd5SPawel Dembicki 		}
146795711cd5SPawel Dembicki 		data[i] = val;
146895711cd5SPawel Dembicki 	}
146995711cd5SPawel Dembicki }
147095711cd5SPawel Dembicki 
1471fb77ffc6SVladimir Oltean static int vsc73xx_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
1472fb77ffc6SVladimir Oltean {
1473fb77ffc6SVladimir Oltean 	struct vsc73xx *vsc = ds->priv;
1474fb77ffc6SVladimir Oltean 
1475fb77ffc6SVladimir Oltean 	return vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port,
14763cf62c81SPawel Dembicki 			     VSC73XX_MAXLEN, new_mtu + ETH_HLEN + ETH_FCS_LEN);
1477fb77ffc6SVladimir Oltean }
1478fb77ffc6SVladimir Oltean 
1479fb77ffc6SVladimir Oltean /* According to application not "VSC7398 Jumbo Frames" setting
14803cf62c81SPawel Dembicki  * up the frame size to 9.6 KB does not affect the performance on standard
1481fb77ffc6SVladimir Oltean  * frames. It is clear from the application note that
1482fb77ffc6SVladimir Oltean  * "9.6 kilobytes" == 9600 bytes.
1483fb77ffc6SVladimir Oltean  */
1484fb77ffc6SVladimir Oltean static int vsc73xx_get_max_mtu(struct dsa_switch *ds, int port)
1485fb77ffc6SVladimir Oltean {
14863cf62c81SPawel Dembicki 	return 9600 - ETH_HLEN - ETH_FCS_LEN;
1487fb77ffc6SVladimir Oltean }
1488fb77ffc6SVladimir Oltean 
1489a026809cSRussell King (Oracle) static void vsc73xx_phylink_get_caps(struct dsa_switch *dsa, int port,
1490a026809cSRussell King (Oracle) 				     struct phylink_config *config)
1491a026809cSRussell King (Oracle) {
1492a026809cSRussell King (Oracle) 	unsigned long *interfaces = config->supported_interfaces;
1493a026809cSRussell King (Oracle) 
1494a026809cSRussell King (Oracle) 	if (port == 5)
1495a026809cSRussell King (Oracle) 		return;
1496a026809cSRussell King (Oracle) 
1497a026809cSRussell King (Oracle) 	if (port == CPU_PORT) {
1498a026809cSRussell King (Oracle) 		__set_bit(PHY_INTERFACE_MODE_MII, interfaces);
1499a026809cSRussell King (Oracle) 		__set_bit(PHY_INTERFACE_MODE_REVMII, interfaces);
1500a026809cSRussell King (Oracle) 		__set_bit(PHY_INTERFACE_MODE_GMII, interfaces);
1501a026809cSRussell King (Oracle) 		__set_bit(PHY_INTERFACE_MODE_RGMII, interfaces);
1502a026809cSRussell King (Oracle) 	}
1503a026809cSRussell King (Oracle) 
1504a026809cSRussell King (Oracle) 	if (port <= 4) {
1505a026809cSRussell King (Oracle) 		/* Internal PHYs */
1506a026809cSRussell King (Oracle) 		__set_bit(PHY_INTERFACE_MODE_INTERNAL, interfaces);
1507a026809cSRussell King (Oracle) 		/* phylib default */
1508a026809cSRussell King (Oracle) 		__set_bit(PHY_INTERFACE_MODE_GMII, interfaces);
1509a026809cSRussell King (Oracle) 	}
1510a026809cSRussell King (Oracle) 
1511a026809cSRussell King (Oracle) 	config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000;
1512a026809cSRussell King (Oracle) }
1513a026809cSRussell King (Oracle) 
15146b783dedSPawel Dembicki static int
15156b783dedSPawel Dembicki vsc73xx_port_vlan_filtering(struct dsa_switch *ds, int port,
15166b783dedSPawel Dembicki 			    bool vlan_filtering, struct netlink_ext_ack *extack)
15176b783dedSPawel Dembicki {
15186b783dedSPawel Dembicki 	struct vsc73xx *vsc = ds->priv;
15196b783dedSPawel Dembicki 
15206b783dedSPawel Dembicki 	/* The commit to hardware processed below is required because vsc73xx
15216b783dedSPawel Dembicki 	 * is using tag_8021q. When vlan_filtering is disabled, tag_8021q uses
15226b783dedSPawel Dembicki 	 * pvid/untagged vlans for port recognition. The values configured for
15236b783dedSPawel Dembicki 	 * vlans and pvid/untagged states are stored in portinfo structure.
15246b783dedSPawel Dembicki 	 * When vlan_filtering is enabled, we need to restore pvid/untagged from
15256b783dedSPawel Dembicki 	 * portinfo structure. Analogous routine is processed when
15266b783dedSPawel Dembicki 	 * vlan_filtering is disabled, but values used for tag_8021q are
15276b783dedSPawel Dembicki 	 * restored.
15286b783dedSPawel Dembicki 	 */
15296b783dedSPawel Dembicki 
15306b783dedSPawel Dembicki 	return vsc73xx_vlan_commit_settings(vsc, port);
15316b783dedSPawel Dembicki }
15326b783dedSPawel Dembicki 
15336b783dedSPawel Dembicki static int vsc73xx_port_vlan_add(struct dsa_switch *ds, int port,
15346b783dedSPawel Dembicki 				 const struct switchdev_obj_port_vlan *vlan,
15356b783dedSPawel Dembicki 				 struct netlink_ext_ack *extack)
15366b783dedSPawel Dembicki {
15376b783dedSPawel Dembicki 	bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
15386b783dedSPawel Dembicki 	bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
15396b783dedSPawel Dembicki 	struct dsa_port *dp = dsa_to_port(ds, port);
15406b783dedSPawel Dembicki 	struct vsc73xx_bridge_vlan *vsc73xx_vlan;
15416b783dedSPawel Dembicki 	struct vsc73xx_vlan_summary summary;
15426b783dedSPawel Dembicki 	struct vsc73xx_portinfo *portinfo;
15436b783dedSPawel Dembicki 	struct vsc73xx *vsc = ds->priv;
15446b783dedSPawel Dembicki 	bool commit_to_hardware;
15456b783dedSPawel Dembicki 	int ret = 0;
15466b783dedSPawel Dembicki 
15476b783dedSPawel Dembicki 	/* Be sure to deny alterations to the configuration done by tag_8021q.
15486b783dedSPawel Dembicki 	 */
15496b783dedSPawel Dembicki 	if (vid_is_dsa_8021q(vlan->vid)) {
15506b783dedSPawel Dembicki 		NL_SET_ERR_MSG_MOD(extack,
15516b783dedSPawel Dembicki 				   "Range 3072-4095 reserved for dsa_8021q operation");
15526b783dedSPawel Dembicki 		return -EBUSY;
15536b783dedSPawel Dembicki 	}
15546b783dedSPawel Dembicki 
15556b783dedSPawel Dembicki 	/* The processed vlan->vid is excluded from the search because the VLAN
15566b783dedSPawel Dembicki 	 * can be re-added with a different set of flags, so it's easiest to
15576b783dedSPawel Dembicki 	 * ignore its old flags from the VLAN database software copy.
15586b783dedSPawel Dembicki 	 */
15596b783dedSPawel Dembicki 	vsc73xx_bridge_vlan_summary(vsc, port, &summary, vlan->vid);
15606b783dedSPawel Dembicki 
15616b783dedSPawel Dembicki 	/* VSC73XX allows only three untagged states: none, one or all */
15626b783dedSPawel Dembicki 	if ((untagged && summary.num_tagged > 0 && summary.num_untagged > 0) ||
15636b783dedSPawel Dembicki 	    (!untagged && summary.num_untagged > 1)) {
15646b783dedSPawel Dembicki 		NL_SET_ERR_MSG_MOD(extack,
15656b783dedSPawel Dembicki 				   "Port can have only none, one or all untagged vlan");
15666b783dedSPawel Dembicki 		return -EBUSY;
15676b783dedSPawel Dembicki 	}
15686b783dedSPawel Dembicki 
15696b783dedSPawel Dembicki 	vsc73xx_vlan = vsc73xx_bridge_vlan_find(vsc, vlan->vid);
15706b783dedSPawel Dembicki 
15716b783dedSPawel Dembicki 	if (!vsc73xx_vlan) {
15726b783dedSPawel Dembicki 		vsc73xx_vlan = kzalloc(sizeof(*vsc73xx_vlan), GFP_KERNEL);
15736b783dedSPawel Dembicki 		if (!vsc73xx_vlan)
15746b783dedSPawel Dembicki 			return -ENOMEM;
15756b783dedSPawel Dembicki 
15766b783dedSPawel Dembicki 		vsc73xx_vlan->vid = vlan->vid;
15776b783dedSPawel Dembicki 
15786b783dedSPawel Dembicki 		list_add_tail(&vsc73xx_vlan->list, &vsc->vlans);
15796b783dedSPawel Dembicki 	}
15806b783dedSPawel Dembicki 
15816b783dedSPawel Dembicki 	vsc73xx_vlan->portmask |= BIT(port);
15826b783dedSPawel Dembicki 
15836b783dedSPawel Dembicki 	/* CPU port must be always tagged because source port identification is
15846b783dedSPawel Dembicki 	 * based on tag_8021q.
15856b783dedSPawel Dembicki 	 */
15866b783dedSPawel Dembicki 	if (port == CPU_PORT)
15876b783dedSPawel Dembicki 		goto update_vlan_table;
15886b783dedSPawel Dembicki 
15896b783dedSPawel Dembicki 	if (untagged)
15906b783dedSPawel Dembicki 		vsc73xx_vlan->untagged |= BIT(port);
15916b783dedSPawel Dembicki 	else
15926b783dedSPawel Dembicki 		vsc73xx_vlan->untagged &= ~BIT(port);
15936b783dedSPawel Dembicki 
15946b783dedSPawel Dembicki 	portinfo = &vsc->portinfo[port];
15956b783dedSPawel Dembicki 
15966b783dedSPawel Dembicki 	if (pvid) {
15976b783dedSPawel Dembicki 		portinfo->pvid_vlan_filtering_configured = true;
15986b783dedSPawel Dembicki 		portinfo->pvid_vlan_filtering = vlan->vid;
15996b783dedSPawel Dembicki 	} else if (portinfo->pvid_vlan_filtering_configured &&
16006b783dedSPawel Dembicki 		   portinfo->pvid_vlan_filtering == vlan->vid) {
16016b783dedSPawel Dembicki 		portinfo->pvid_vlan_filtering_configured = false;
16026b783dedSPawel Dembicki 	}
16036b783dedSPawel Dembicki 
16046b783dedSPawel Dembicki 	commit_to_hardware = !vsc73xx_tag_8021q_active(dp);
16056b783dedSPawel Dembicki 	if (commit_to_hardware) {
16066b783dedSPawel Dembicki 		ret = vsc73xx_vlan_commit_settings(vsc, port);
16076b783dedSPawel Dembicki 		if (ret)
16086b783dedSPawel Dembicki 			goto err;
16096b783dedSPawel Dembicki 	}
16106b783dedSPawel Dembicki 
16116b783dedSPawel Dembicki update_vlan_table:
16126b783dedSPawel Dembicki 	ret = vsc73xx_update_vlan_table(vsc, port, vlan->vid, true);
16136b783dedSPawel Dembicki 	if (!ret)
16146b783dedSPawel Dembicki 		return 0;
16156b783dedSPawel Dembicki err:
16166b783dedSPawel Dembicki 	vsc73xx_bridge_vlan_remove_port(vsc73xx_vlan, port);
16176b783dedSPawel Dembicki 	return ret;
16186b783dedSPawel Dembicki }
16196b783dedSPawel Dembicki 
16206b783dedSPawel Dembicki static int vsc73xx_port_vlan_del(struct dsa_switch *ds, int port,
16216b783dedSPawel Dembicki 				 const struct switchdev_obj_port_vlan *vlan)
16226b783dedSPawel Dembicki {
16236b783dedSPawel Dembicki 	struct vsc73xx_bridge_vlan *vsc73xx_vlan;
16246b783dedSPawel Dembicki 	struct vsc73xx_portinfo *portinfo;
16256b783dedSPawel Dembicki 	struct vsc73xx *vsc = ds->priv;
16266b783dedSPawel Dembicki 	bool commit_to_hardware;
16276b783dedSPawel Dembicki 	int ret;
16286b783dedSPawel Dembicki 
16296b783dedSPawel Dembicki 	ret = vsc73xx_update_vlan_table(vsc, port, vlan->vid, false);
16306b783dedSPawel Dembicki 	if (ret)
16316b783dedSPawel Dembicki 		return ret;
16326b783dedSPawel Dembicki 
16336b783dedSPawel Dembicki 	portinfo = &vsc->portinfo[port];
16346b783dedSPawel Dembicki 
16356b783dedSPawel Dembicki 	if (portinfo->pvid_vlan_filtering_configured &&
16366b783dedSPawel Dembicki 	    portinfo->pvid_vlan_filtering == vlan->vid)
16376b783dedSPawel Dembicki 		portinfo->pvid_vlan_filtering_configured = false;
16386b783dedSPawel Dembicki 
16396b783dedSPawel Dembicki 	vsc73xx_vlan = vsc73xx_bridge_vlan_find(vsc, vlan->vid);
16406b783dedSPawel Dembicki 
16416b783dedSPawel Dembicki 	if (vsc73xx_vlan)
16426b783dedSPawel Dembicki 		vsc73xx_bridge_vlan_remove_port(vsc73xx_vlan, port);
16436b783dedSPawel Dembicki 
16446b783dedSPawel Dembicki 	commit_to_hardware = !vsc73xx_tag_8021q_active(dsa_to_port(ds, port));
1645e3386ec4SPawel Dembicki 
16466b783dedSPawel Dembicki 	if (commit_to_hardware)
16476b783dedSPawel Dembicki 		return vsc73xx_vlan_commit_settings(vsc, port);
16486b783dedSPawel Dembicki 
16496b783dedSPawel Dembicki 	return 0;
16506b783dedSPawel Dembicki }
16516b783dedSPawel Dembicki 
1652e3386ec4SPawel Dembicki static int vsc73xx_tag_8021q_vlan_add(struct dsa_switch *ds, int port, u16 vid,
1653e3386ec4SPawel Dembicki 				      u16 flags)
1654e3386ec4SPawel Dembicki {
1655e3386ec4SPawel Dembicki 	bool pvid = flags & BRIDGE_VLAN_INFO_PVID;
1656e3386ec4SPawel Dembicki 	struct vsc73xx_portinfo *portinfo;
1657e3386ec4SPawel Dembicki 	struct vsc73xx *vsc = ds->priv;
1658e3386ec4SPawel Dembicki 	bool commit_to_hardware;
1659e3386ec4SPawel Dembicki 	int ret;
1660e3386ec4SPawel Dembicki 
1661e3386ec4SPawel Dembicki 	portinfo = &vsc->portinfo[port];
1662e3386ec4SPawel Dembicki 
1663e3386ec4SPawel Dembicki 	if (pvid) {
1664e3386ec4SPawel Dembicki 		portinfo->pvid_tag_8021q_configured = true;
1665e3386ec4SPawel Dembicki 		portinfo->pvid_tag_8021q = vid;
1666e3386ec4SPawel Dembicki 	}
1667e3386ec4SPawel Dembicki 
1668e3386ec4SPawel Dembicki 	commit_to_hardware = vsc73xx_tag_8021q_active(dsa_to_port(ds, port));
1669e3386ec4SPawel Dembicki 	if (commit_to_hardware) {
1670e3386ec4SPawel Dembicki 		ret = vsc73xx_vlan_commit_settings(vsc, port);
1671e3386ec4SPawel Dembicki 		if (ret)
1672e3386ec4SPawel Dembicki 			return ret;
1673e3386ec4SPawel Dembicki 	}
1674e3386ec4SPawel Dembicki 
1675e3386ec4SPawel Dembicki 	return vsc73xx_update_vlan_table(vsc, port, vid, true);
1676e3386ec4SPawel Dembicki }
1677e3386ec4SPawel Dembicki 
1678e3386ec4SPawel Dembicki static int vsc73xx_tag_8021q_vlan_del(struct dsa_switch *ds, int port, u16 vid)
1679e3386ec4SPawel Dembicki {
1680e3386ec4SPawel Dembicki 	struct vsc73xx_portinfo *portinfo;
1681e3386ec4SPawel Dembicki 	struct vsc73xx *vsc = ds->priv;
1682e3386ec4SPawel Dembicki 
1683e3386ec4SPawel Dembicki 	portinfo = &vsc->portinfo[port];
1684e3386ec4SPawel Dembicki 
1685e3386ec4SPawel Dembicki 	if (portinfo->pvid_tag_8021q_configured &&
1686e3386ec4SPawel Dembicki 	    portinfo->pvid_tag_8021q == vid) {
1687e3386ec4SPawel Dembicki 		struct dsa_port *dp = dsa_to_port(ds, port);
1688e3386ec4SPawel Dembicki 		bool commit_to_hardware;
1689e3386ec4SPawel Dembicki 		int err;
1690e3386ec4SPawel Dembicki 
1691e3386ec4SPawel Dembicki 		portinfo->pvid_tag_8021q_configured = false;
1692e3386ec4SPawel Dembicki 
1693e3386ec4SPawel Dembicki 		commit_to_hardware = vsc73xx_tag_8021q_active(dp);
1694e3386ec4SPawel Dembicki 		if (commit_to_hardware) {
1695e3386ec4SPawel Dembicki 			err = vsc73xx_vlan_commit_settings(vsc, port);
1696e3386ec4SPawel Dembicki 			if (err)
1697e3386ec4SPawel Dembicki 				return err;
1698e3386ec4SPawel Dembicki 		}
1699e3386ec4SPawel Dembicki 	}
1700e3386ec4SPawel Dembicki 
1701e3386ec4SPawel Dembicki 	return vsc73xx_update_vlan_table(vsc, port, vid, false);
1702e3386ec4SPawel Dembicki }
1703e3386ec4SPawel Dembicki 
1704259a7061SPawel Dembicki static int vsc73xx_port_pre_bridge_flags(struct dsa_switch *ds, int port,
1705259a7061SPawel Dembicki 					 struct switchdev_brport_flags flags,
1706259a7061SPawel Dembicki 					 struct netlink_ext_ack *extack)
1707259a7061SPawel Dembicki {
1708259a7061SPawel Dembicki 	if (flags.mask & ~BR_LEARNING)
1709259a7061SPawel Dembicki 		return -EINVAL;
1710259a7061SPawel Dembicki 
1711259a7061SPawel Dembicki 	return 0;
1712259a7061SPawel Dembicki }
1713259a7061SPawel Dembicki 
1714259a7061SPawel Dembicki static int vsc73xx_port_bridge_flags(struct dsa_switch *ds, int port,
1715259a7061SPawel Dembicki 				     struct switchdev_brport_flags flags,
1716259a7061SPawel Dembicki 				     struct netlink_ext_ack *extack)
1717259a7061SPawel Dembicki {
1718259a7061SPawel Dembicki 	if (flags.mask & BR_LEARNING) {
1719259a7061SPawel Dembicki 		u32 val = flags.val & BR_LEARNING ? BIT(port) : 0;
1720259a7061SPawel Dembicki 		struct vsc73xx *vsc = ds->priv;
1721259a7061SPawel Dembicki 
1722259a7061SPawel Dembicki 		return vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0,
1723259a7061SPawel Dembicki 					   VSC73XX_LEARNMASK, BIT(port), val);
1724259a7061SPawel Dembicki 	}
1725259a7061SPawel Dembicki 
1726259a7061SPawel Dembicki 	return 0;
1727259a7061SPawel Dembicki }
1728259a7061SPawel Dembicki 
17291e5b23e5SPawel Dembicki static void vsc73xx_refresh_fwd_map(struct dsa_switch *ds, int port, u8 state)
17301e5b23e5SPawel Dembicki {
17311e5b23e5SPawel Dembicki 	struct dsa_port *other_dp, *dp = dsa_to_port(ds, port);
17321e5b23e5SPawel Dembicki 	struct vsc73xx *vsc = ds->priv;
17331e5b23e5SPawel Dembicki 	u16 mask;
17341e5b23e5SPawel Dembicki 
17351e5b23e5SPawel Dembicki 	if (state != BR_STATE_FORWARDING) {
17361e5b23e5SPawel Dembicki 		/* Ports that aren't in the forwarding state must not
17371e5b23e5SPawel Dembicki 		 * forward packets anywhere.
17381e5b23e5SPawel Dembicki 		 */
17391e5b23e5SPawel Dembicki 		vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0,
17401e5b23e5SPawel Dembicki 				    VSC73XX_SRCMASKS + port,
17411e5b23e5SPawel Dembicki 				    VSC73XX_SRCMASKS_PORTS_MASK, 0);
17421e5b23e5SPawel Dembicki 
17431e5b23e5SPawel Dembicki 		dsa_switch_for_each_available_port(other_dp, ds) {
17441e5b23e5SPawel Dembicki 			if (other_dp == dp)
17451e5b23e5SPawel Dembicki 				continue;
17461e5b23e5SPawel Dembicki 			vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0,
17471e5b23e5SPawel Dembicki 					    VSC73XX_SRCMASKS + other_dp->index,
17481e5b23e5SPawel Dembicki 					    BIT(port), 0);
17491e5b23e5SPawel Dembicki 		}
17501e5b23e5SPawel Dembicki 
17511e5b23e5SPawel Dembicki 		return;
17521e5b23e5SPawel Dembicki 	}
17531e5b23e5SPawel Dembicki 
17541e5b23e5SPawel Dembicki 	/* Forwarding ports must forward to the CPU and to other ports
17551e5b23e5SPawel Dembicki 	 * in the same bridge
17561e5b23e5SPawel Dembicki 	 */
17571e5b23e5SPawel Dembicki 	vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0,
17581e5b23e5SPawel Dembicki 			    VSC73XX_SRCMASKS + CPU_PORT, BIT(port), BIT(port));
17591e5b23e5SPawel Dembicki 
17601e5b23e5SPawel Dembicki 	mask = BIT(CPU_PORT);
17611e5b23e5SPawel Dembicki 
17621e5b23e5SPawel Dembicki 	dsa_switch_for_each_user_port(other_dp, ds) {
17631e5b23e5SPawel Dembicki 		int other_port = other_dp->index;
17641e5b23e5SPawel Dembicki 
17651e5b23e5SPawel Dembicki 		if (port == other_port || !dsa_port_bridge_same(dp, other_dp) ||
17661e5b23e5SPawel Dembicki 		    other_dp->stp_state != BR_STATE_FORWARDING)
17671e5b23e5SPawel Dembicki 			continue;
17681e5b23e5SPawel Dembicki 
17691e5b23e5SPawel Dembicki 		mask |= BIT(other_port);
17701e5b23e5SPawel Dembicki 
17711e5b23e5SPawel Dembicki 		vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0,
17721e5b23e5SPawel Dembicki 				    VSC73XX_SRCMASKS + other_port,
17731e5b23e5SPawel Dembicki 				    BIT(port), BIT(port));
17741e5b23e5SPawel Dembicki 	}
17751e5b23e5SPawel Dembicki 
17761e5b23e5SPawel Dembicki 	vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0,
17771e5b23e5SPawel Dembicki 			    VSC73XX_SRCMASKS + port,
17781e5b23e5SPawel Dembicki 			    VSC73XX_SRCMASKS_PORTS_MASK, mask);
17791e5b23e5SPawel Dembicki }
17801e5b23e5SPawel Dembicki 
17811e5b23e5SPawel Dembicki /* FIXME: STP frames aren't forwarded at this moment. BPDU frames are
17821e5b23e5SPawel Dembicki  * forwarded only from and to PI/SI interface. For more info see chapter
17831e5b23e5SPawel Dembicki  * 2.7.1 (CPU Forwarding) in datasheet.
17841e5b23e5SPawel Dembicki  * This function is required for tag_8021q operations.
17851e5b23e5SPawel Dembicki  */
17861e5b23e5SPawel Dembicki static void vsc73xx_port_stp_state_set(struct dsa_switch *ds, int port,
17871e5b23e5SPawel Dembicki 				       u8 state)
17881e5b23e5SPawel Dembicki {
1789259a7061SPawel Dembicki 	struct dsa_port *dp = dsa_to_port(ds, port);
17901e5b23e5SPawel Dembicki 	struct vsc73xx *vsc = ds->priv;
1791259a7061SPawel Dembicki 	u32 val = 0;
1792259a7061SPawel Dembicki 
1793259a7061SPawel Dembicki 	if (state == BR_STATE_LEARNING || state == BR_STATE_FORWARDING)
1794259a7061SPawel Dembicki 		val = dp->learning ? BIT(port) : 0;
1795259a7061SPawel Dembicki 
1796259a7061SPawel Dembicki 	vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0,
1797259a7061SPawel Dembicki 			    VSC73XX_LEARNMASK, BIT(port), val);
17981e5b23e5SPawel Dembicki 
17991e5b23e5SPawel Dembicki 	val = (state == BR_STATE_BLOCKING || state == BR_STATE_DISABLED) ?
18001e5b23e5SPawel Dembicki 	      0 : BIT(port);
18011e5b23e5SPawel Dembicki 	vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0,
18021e5b23e5SPawel Dembicki 			    VSC73XX_RECVMASK, BIT(port), val);
18031e5b23e5SPawel Dembicki 
18041e5b23e5SPawel Dembicki 	/* CPU Port should always forward packets when user ports are forwarding
18051e5b23e5SPawel Dembicki 	 * so let's configure it from other ports only.
18061e5b23e5SPawel Dembicki 	 */
18071e5b23e5SPawel Dembicki 	if (port != CPU_PORT)
18081e5b23e5SPawel Dembicki 		vsc73xx_refresh_fwd_map(ds, port, state);
18091e5b23e5SPawel Dembicki }
18101e5b23e5SPawel Dembicki 
181121fc3416SPawel Dembicki static const struct phylink_mac_ops vsc73xx_phylink_mac_ops = {
181221fc3416SPawel Dembicki 	.mac_config = vsc73xx_mac_config,
181321fc3416SPawel Dembicki 	.mac_link_down = vsc73xx_mac_link_down,
181421fc3416SPawel Dembicki 	.mac_link_up = vsc73xx_mac_link_up,
181521fc3416SPawel Dembicki };
181621fc3416SPawel Dembicki 
181795711cd5SPawel Dembicki static const struct dsa_switch_ops vsc73xx_ds_ops = {
181895711cd5SPawel Dembicki 	.get_tag_protocol = vsc73xx_get_tag_protocol,
181995711cd5SPawel Dembicki 	.setup = vsc73xx_setup,
1820e3386ec4SPawel Dembicki 	.teardown = vsc73xx_teardown,
182195711cd5SPawel Dembicki 	.phy_read = vsc73xx_phy_read,
182295711cd5SPawel Dembicki 	.phy_write = vsc73xx_phy_write,
182395711cd5SPawel Dembicki 	.get_strings = vsc73xx_get_strings,
182495711cd5SPawel Dembicki 	.get_ethtool_stats = vsc73xx_get_ethtool_stats,
182595711cd5SPawel Dembicki 	.get_sset_count = vsc73xx_get_sset_count,
182695711cd5SPawel Dembicki 	.port_enable = vsc73xx_port_enable,
182795711cd5SPawel Dembicki 	.port_disable = vsc73xx_port_disable,
1828259a7061SPawel Dembicki 	.port_pre_bridge_flags = vsc73xx_port_pre_bridge_flags,
1829259a7061SPawel Dembicki 	.port_bridge_flags = vsc73xx_port_bridge_flags,
18306dfaaa27SPawel Dembicki 	.port_bridge_join = dsa_tag_8021q_bridge_join,
18316dfaaa27SPawel Dembicki 	.port_bridge_leave = dsa_tag_8021q_bridge_leave,
1832fb77ffc6SVladimir Oltean 	.port_change_mtu = vsc73xx_change_mtu,
1833fb77ffc6SVladimir Oltean 	.port_max_mtu = vsc73xx_get_max_mtu,
18341e5b23e5SPawel Dembicki 	.port_stp_state_set = vsc73xx_port_stp_state_set,
18356b783dedSPawel Dembicki 	.port_vlan_filtering = vsc73xx_port_vlan_filtering,
18366b783dedSPawel Dembicki 	.port_vlan_add = vsc73xx_port_vlan_add,
18376b783dedSPawel Dembicki 	.port_vlan_del = vsc73xx_port_vlan_del,
1838a026809cSRussell King (Oracle) 	.phylink_get_caps = vsc73xx_phylink_get_caps,
1839e3386ec4SPawel Dembicki 	.tag_8021q_vlan_add = vsc73xx_tag_8021q_vlan_add,
1840e3386ec4SPawel Dembicki 	.tag_8021q_vlan_del = vsc73xx_tag_8021q_vlan_del,
184195711cd5SPawel Dembicki };
184295711cd5SPawel Dembicki 
184395711cd5SPawel Dembicki static int vsc73xx_gpio_get(struct gpio_chip *chip, unsigned int offset)
184495711cd5SPawel Dembicki {
184595711cd5SPawel Dembicki 	struct vsc73xx *vsc = gpiochip_get_data(chip);
184695711cd5SPawel Dembicki 	u32 val;
184795711cd5SPawel Dembicki 	int ret;
184895711cd5SPawel Dembicki 
184995711cd5SPawel Dembicki 	ret = vsc73xx_read(vsc, VSC73XX_BLOCK_SYSTEM, 0,
185095711cd5SPawel Dembicki 			   VSC73XX_GPIO, &val);
185195711cd5SPawel Dembicki 	if (ret)
185295711cd5SPawel Dembicki 		return ret;
185395711cd5SPawel Dembicki 
185495711cd5SPawel Dembicki 	return !!(val & BIT(offset));
185595711cd5SPawel Dembicki }
185695711cd5SPawel Dembicki 
185795711cd5SPawel Dembicki static void vsc73xx_gpio_set(struct gpio_chip *chip, unsigned int offset,
185895711cd5SPawel Dembicki 			     int val)
185995711cd5SPawel Dembicki {
186095711cd5SPawel Dembicki 	struct vsc73xx *vsc = gpiochip_get_data(chip);
186195711cd5SPawel Dembicki 	u32 tmp = val ? BIT(offset) : 0;
186295711cd5SPawel Dembicki 
186395711cd5SPawel Dembicki 	vsc73xx_update_bits(vsc, VSC73XX_BLOCK_SYSTEM, 0,
186495711cd5SPawel Dembicki 			    VSC73XX_GPIO, BIT(offset), tmp);
186595711cd5SPawel Dembicki }
186695711cd5SPawel Dembicki 
186795711cd5SPawel Dembicki static int vsc73xx_gpio_direction_output(struct gpio_chip *chip,
186895711cd5SPawel Dembicki 					 unsigned int offset, int val)
186995711cd5SPawel Dembicki {
187095711cd5SPawel Dembicki 	struct vsc73xx *vsc = gpiochip_get_data(chip);
187195711cd5SPawel Dembicki 	u32 tmp = val ? BIT(offset) : 0;
187295711cd5SPawel Dembicki 
187395711cd5SPawel Dembicki 	return vsc73xx_update_bits(vsc, VSC73XX_BLOCK_SYSTEM, 0,
187495711cd5SPawel Dembicki 				   VSC73XX_GPIO, BIT(offset + 4) | BIT(offset),
187595711cd5SPawel Dembicki 				   BIT(offset + 4) | tmp);
187695711cd5SPawel Dembicki }
187795711cd5SPawel Dembicki 
187895711cd5SPawel Dembicki static int vsc73xx_gpio_direction_input(struct gpio_chip *chip,
187995711cd5SPawel Dembicki 					unsigned int offset)
188095711cd5SPawel Dembicki {
188195711cd5SPawel Dembicki 	struct vsc73xx *vsc = gpiochip_get_data(chip);
188295711cd5SPawel Dembicki 
188395711cd5SPawel Dembicki 	return  vsc73xx_update_bits(vsc, VSC73XX_BLOCK_SYSTEM, 0,
188495711cd5SPawel Dembicki 				    VSC73XX_GPIO, BIT(offset + 4),
188595711cd5SPawel Dembicki 				    0);
188695711cd5SPawel Dembicki }
188795711cd5SPawel Dembicki 
188895711cd5SPawel Dembicki static int vsc73xx_gpio_get_direction(struct gpio_chip *chip,
188995711cd5SPawel Dembicki 				      unsigned int offset)
189095711cd5SPawel Dembicki {
189195711cd5SPawel Dembicki 	struct vsc73xx *vsc = gpiochip_get_data(chip);
189295711cd5SPawel Dembicki 	u32 val;
189395711cd5SPawel Dembicki 	int ret;
189495711cd5SPawel Dembicki 
189595711cd5SPawel Dembicki 	ret = vsc73xx_read(vsc, VSC73XX_BLOCK_SYSTEM, 0,
189695711cd5SPawel Dembicki 			   VSC73XX_GPIO, &val);
189795711cd5SPawel Dembicki 	if (ret)
189895711cd5SPawel Dembicki 		return ret;
189995711cd5SPawel Dembicki 
190095711cd5SPawel Dembicki 	return !(val & BIT(offset + 4));
190195711cd5SPawel Dembicki }
190295711cd5SPawel Dembicki 
190395711cd5SPawel Dembicki static int vsc73xx_gpio_probe(struct vsc73xx *vsc)
190495711cd5SPawel Dembicki {
190595711cd5SPawel Dembicki 	int ret;
190695711cd5SPawel Dembicki 
190795711cd5SPawel Dembicki 	vsc->gc.label = devm_kasprintf(vsc->dev, GFP_KERNEL, "VSC%04x",
190895711cd5SPawel Dembicki 				       vsc->chipid);
1909776dac5aSKunwu Chan 	if (!vsc->gc.label)
1910776dac5aSKunwu Chan 		return -ENOMEM;
191195711cd5SPawel Dembicki 	vsc->gc.ngpio = 4;
191295711cd5SPawel Dembicki 	vsc->gc.owner = THIS_MODULE;
191395711cd5SPawel Dembicki 	vsc->gc.parent = vsc->dev;
191495711cd5SPawel Dembicki 	vsc->gc.base = -1;
191595711cd5SPawel Dembicki 	vsc->gc.get = vsc73xx_gpio_get;
191695711cd5SPawel Dembicki 	vsc->gc.set = vsc73xx_gpio_set;
191795711cd5SPawel Dembicki 	vsc->gc.direction_input = vsc73xx_gpio_direction_input;
191895711cd5SPawel Dembicki 	vsc->gc.direction_output = vsc73xx_gpio_direction_output;
191995711cd5SPawel Dembicki 	vsc->gc.get_direction = vsc73xx_gpio_get_direction;
192095711cd5SPawel Dembicki 	vsc->gc.can_sleep = true;
192195711cd5SPawel Dembicki 	ret = devm_gpiochip_add_data(vsc->dev, &vsc->gc, vsc);
192295711cd5SPawel Dembicki 	if (ret) {
192395711cd5SPawel Dembicki 		dev_err(vsc->dev, "unable to register GPIO chip\n");
192495711cd5SPawel Dembicki 		return ret;
192595711cd5SPawel Dembicki 	}
192695711cd5SPawel Dembicki 	return 0;
192795711cd5SPawel Dembicki }
192895711cd5SPawel Dembicki 
192995711cd5SPawel Dembicki int vsc73xx_probe(struct vsc73xx *vsc)
193095711cd5SPawel Dembicki {
193195711cd5SPawel Dembicki 	struct device *dev = vsc->dev;
193295711cd5SPawel Dembicki 	int ret;
193395711cd5SPawel Dembicki 
193495711cd5SPawel Dembicki 	/* Release reset, if any */
193595711cd5SPawel Dembicki 	vsc->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
193695711cd5SPawel Dembicki 	if (IS_ERR(vsc->reset)) {
193795711cd5SPawel Dembicki 		dev_err(dev, "failed to get RESET GPIO\n");
193895711cd5SPawel Dembicki 		return PTR_ERR(vsc->reset);
193995711cd5SPawel Dembicki 	}
194095711cd5SPawel Dembicki 	if (vsc->reset)
194195711cd5SPawel Dembicki 		/* Wait 20ms according to datasheet table 245 */
194295711cd5SPawel Dembicki 		msleep(20);
194395711cd5SPawel Dembicki 
194495711cd5SPawel Dembicki 	ret = vsc73xx_detect(vsc);
19451da39ff0SPawel Dembicki 	if (ret == -EAGAIN) {
19461da39ff0SPawel Dembicki 		dev_err(vsc->dev,
19471da39ff0SPawel Dembicki 			"Chip seems to be out of control. Assert reset and try again.\n");
19481da39ff0SPawel Dembicki 		gpiod_set_value_cansleep(vsc->reset, 1);
19491da39ff0SPawel Dembicki 		/* Reset pulse should be 20ns minimum, according to datasheet
19501da39ff0SPawel Dembicki 		 * table 245, so 10us should be fine
19511da39ff0SPawel Dembicki 		 */
19521da39ff0SPawel Dembicki 		usleep_range(10, 100);
19531da39ff0SPawel Dembicki 		gpiod_set_value_cansleep(vsc->reset, 0);
19541da39ff0SPawel Dembicki 		/* Wait 20ms according to datasheet table 245 */
19551da39ff0SPawel Dembicki 		msleep(20);
19561da39ff0SPawel Dembicki 		ret = vsc73xx_detect(vsc);
19571da39ff0SPawel Dembicki 	}
195895711cd5SPawel Dembicki 	if (ret) {
195995711cd5SPawel Dembicki 		dev_err(dev, "no chip found (%d)\n", ret);
196095711cd5SPawel Dembicki 		return -ENODEV;
196195711cd5SPawel Dembicki 	}
196295711cd5SPawel Dembicki 
196395711cd5SPawel Dembicki 	eth_random_addr(vsc->addr);
196495711cd5SPawel Dembicki 	dev_info(vsc->dev,
196595711cd5SPawel Dembicki 		 "MAC for control frames: %02X:%02X:%02X:%02X:%02X:%02X\n",
196695711cd5SPawel Dembicki 		 vsc->addr[0], vsc->addr[1], vsc->addr[2],
196795711cd5SPawel Dembicki 		 vsc->addr[3], vsc->addr[4], vsc->addr[5]);
196895711cd5SPawel Dembicki 
19697e99e347SVivien Didelot 	vsc->ds = devm_kzalloc(dev, sizeof(*vsc->ds), GFP_KERNEL);
197095711cd5SPawel Dembicki 	if (!vsc->ds)
197195711cd5SPawel Dembicki 		return -ENOMEM;
19727e99e347SVivien Didelot 
19737e99e347SVivien Didelot 	vsc->ds->dev = dev;
19746cc5280aSPawel Dembicki 	vsc->ds->num_ports = VSC73XX_MAX_NUM_PORTS;
197595711cd5SPawel Dembicki 	vsc->ds->priv = vsc;
197695711cd5SPawel Dembicki 
197795711cd5SPawel Dembicki 	vsc->ds->ops = &vsc73xx_ds_ops;
197821fc3416SPawel Dembicki 	vsc->ds->phylink_mac_ops = &vsc73xx_phylink_mac_ops;
197995711cd5SPawel Dembicki 	ret = dsa_register_switch(vsc->ds);
198095711cd5SPawel Dembicki 	if (ret) {
198195711cd5SPawel Dembicki 		dev_err(dev, "unable to register switch (%d)\n", ret);
198295711cd5SPawel Dembicki 		return ret;
198395711cd5SPawel Dembicki 	}
198495711cd5SPawel Dembicki 
198595711cd5SPawel Dembicki 	ret = vsc73xx_gpio_probe(vsc);
198695711cd5SPawel Dembicki 	if (ret) {
198795711cd5SPawel Dembicki 		dsa_unregister_switch(vsc->ds);
198895711cd5SPawel Dembicki 		return ret;
198995711cd5SPawel Dembicki 	}
199095711cd5SPawel Dembicki 
199195711cd5SPawel Dembicki 	return 0;
199295711cd5SPawel Dembicki }
199395711cd5SPawel Dembicki EXPORT_SYMBOL(vsc73xx_probe);
199495711cd5SPawel Dembicki 
1995e99fa423SUwe Kleine-König void vsc73xx_remove(struct vsc73xx *vsc)
199695711cd5SPawel Dembicki {
199795711cd5SPawel Dembicki 	dsa_unregister_switch(vsc->ds);
199895711cd5SPawel Dembicki 	gpiod_set_value(vsc->reset, 1);
199995711cd5SPawel Dembicki }
200095711cd5SPawel Dembicki EXPORT_SYMBOL(vsc73xx_remove);
200195711cd5SPawel Dembicki 
20020650bf52SVladimir Oltean void vsc73xx_shutdown(struct vsc73xx *vsc)
20030650bf52SVladimir Oltean {
20040650bf52SVladimir Oltean 	dsa_switch_shutdown(vsc->ds);
20050650bf52SVladimir Oltean }
20060650bf52SVladimir Oltean EXPORT_SYMBOL(vsc73xx_shutdown);
20070650bf52SVladimir Oltean 
200895711cd5SPawel Dembicki MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
200995711cd5SPawel Dembicki MODULE_DESCRIPTION("Vitesse VSC7385/7388/7395/7398 driver");
201095711cd5SPawel Dembicki MODULE_LICENSE("GPL v2");
2011