16f8d3f33SWingman Kwok /*
290cff9e2SWingman Kwok  * Keystone GBE and XGBE subsystem code
36f8d3f33SWingman Kwok  *
46f8d3f33SWingman Kwok  * Copyright (C) 2014 Texas Instruments Incorporated
56f8d3f33SWingman Kwok  * Authors:	Sandeep Nair <sandeep_n@ti.com>
66f8d3f33SWingman Kwok  *		Sandeep Paulraj <s-paulraj@ti.com>
76f8d3f33SWingman Kwok  *		Cyril Chemparathy <cyril@ti.com>
86f8d3f33SWingman Kwok  *		Santosh Shilimkar <santosh.shilimkar@ti.com>
96f8d3f33SWingman Kwok  *		Wingman Kwok <w-kwok2@ti.com>
106f8d3f33SWingman Kwok  *
116f8d3f33SWingman Kwok  * This program is free software; you can redistribute it and/or
126f8d3f33SWingman Kwok  * modify it under the terms of the GNU General Public License as
136f8d3f33SWingman Kwok  * published by the Free Software Foundation version 2.
146f8d3f33SWingman Kwok  *
156f8d3f33SWingman Kwok  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
166f8d3f33SWingman Kwok  * kind, whether express or implied; without even the implied warranty
176f8d3f33SWingman Kwok  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
186f8d3f33SWingman Kwok  * GNU General Public License for more details.
196f8d3f33SWingman Kwok  */
206f8d3f33SWingman Kwok 
216f8d3f33SWingman Kwok #include <linux/io.h>
2258c11b5fSKaricheri, Muralidharan #include <linux/module.h>
236f8d3f33SWingman Kwok #include <linux/of_mdio.h>
246f8d3f33SWingman Kwok #include <linux/of_address.h>
256f8d3f33SWingman Kwok #include <linux/if_vlan.h>
266f8d3f33SWingman Kwok #include <linux/ethtool.h>
276f8d3f33SWingman Kwok 
286f8d3f33SWingman Kwok #include "cpsw_ale.h"
296f8d3f33SWingman Kwok #include "netcp.h"
306f8d3f33SWingman Kwok 
316f8d3f33SWingman Kwok #define NETCP_DRIVER_NAME		"TI KeyStone Ethernet Driver"
326f8d3f33SWingman Kwok #define NETCP_DRIVER_VERSION		"v1.0"
336f8d3f33SWingman Kwok 
346f8d3f33SWingman Kwok #define GBE_IDENT(reg)			((reg >> 16) & 0xffff)
356f8d3f33SWingman Kwok #define GBE_MAJOR_VERSION(reg)		(reg >> 8 & 0x7)
366f8d3f33SWingman Kwok #define GBE_MINOR_VERSION(reg)		(reg & 0xff)
376f8d3f33SWingman Kwok #define GBE_RTL_VERSION(reg)		((reg >> 11) & 0x1f)
386f8d3f33SWingman Kwok 
396f8d3f33SWingman Kwok /* 1G Ethernet SS defines */
406f8d3f33SWingman Kwok #define GBE_MODULE_NAME			"netcp-gbe"
416f8d3f33SWingman Kwok #define GBE_SS_VERSION_14		0x4ed21104
426f8d3f33SWingman Kwok 
4321e0e0ddSKaricheri, Muralidharan #define GBE_SS_REG_INDEX		0
4421e0e0ddSKaricheri, Muralidharan #define GBE_SGMII34_REG_INDEX		1
4521e0e0ddSKaricheri, Muralidharan #define GBE_SM_REG_INDEX		2
4621e0e0ddSKaricheri, Muralidharan /* offset relative to base of GBE_SS_REG_INDEX */
476f8d3f33SWingman Kwok #define GBE13_SGMII_MODULE_OFFSET	0x100
4821e0e0ddSKaricheri, Muralidharan /* offset relative to base of GBE_SM_REG_INDEX */
4921e0e0ddSKaricheri, Muralidharan #define GBE13_HOST_PORT_OFFSET		0x34
5021e0e0ddSKaricheri, Muralidharan #define GBE13_SLAVE_PORT_OFFSET		0x60
5121e0e0ddSKaricheri, Muralidharan #define GBE13_EMAC_OFFSET		0x100
5221e0e0ddSKaricheri, Muralidharan #define GBE13_SLAVE_PORT2_OFFSET	0x200
5321e0e0ddSKaricheri, Muralidharan #define GBE13_HW_STATS_OFFSET		0x300
5421e0e0ddSKaricheri, Muralidharan #define GBE13_ALE_OFFSET		0x600
556f8d3f33SWingman Kwok #define GBE13_HOST_PORT_NUM		0
566f8d3f33SWingman Kwok #define GBE13_NUM_ALE_ENTRIES		1024
576f8d3f33SWingman Kwok 
589a391c7bSWingMan Kwok /* 1G Ethernet NU SS defines */
599a391c7bSWingMan Kwok #define GBENU_MODULE_NAME		"netcp-gbenu"
609a391c7bSWingMan Kwok #define GBE_SS_ID_NU			0x4ee6
619a391c7bSWingMan Kwok #define GBE_SS_ID_2U			0x4ee8
629a391c7bSWingMan Kwok 
639a391c7bSWingMan Kwok #define IS_SS_ID_MU(d) \
649a391c7bSWingMan Kwok 	((GBE_IDENT((d)->ss_version) == GBE_SS_ID_NU) || \
659a391c7bSWingMan Kwok 	 (GBE_IDENT((d)->ss_version) == GBE_SS_ID_2U))
669a391c7bSWingMan Kwok 
679a391c7bSWingMan Kwok #define IS_SS_ID_NU(d) \
689a391c7bSWingMan Kwok 	(GBE_IDENT((d)->ss_version) == GBE_SS_ID_NU)
699a391c7bSWingMan Kwok 
709a391c7bSWingMan Kwok #define GBENU_SS_REG_INDEX		0
719a391c7bSWingMan Kwok #define GBENU_SM_REG_INDEX		1
729a391c7bSWingMan Kwok #define GBENU_SGMII_MODULE_OFFSET	0x100
739a391c7bSWingMan Kwok #define GBENU_HOST_PORT_OFFSET		0x1000
749a391c7bSWingMan Kwok #define GBENU_SLAVE_PORT_OFFSET		0x2000
759a391c7bSWingMan Kwok #define GBENU_EMAC_OFFSET		0x2330
769a391c7bSWingMan Kwok #define GBENU_HW_STATS_OFFSET		0x1a000
779a391c7bSWingMan Kwok #define GBENU_ALE_OFFSET		0x1e000
789a391c7bSWingMan Kwok #define GBENU_HOST_PORT_NUM		0
799a391c7bSWingMan Kwok #define GBENU_NUM_ALE_ENTRIES		1024
809a391c7bSWingMan Kwok 
8190cff9e2SWingman Kwok /* 10G Ethernet SS defines */
8290cff9e2SWingman Kwok #define XGBE_MODULE_NAME		"netcp-xgbe"
8390cff9e2SWingman Kwok #define XGBE_SS_VERSION_10		0x4ee42100
8490cff9e2SWingman Kwok 
8521e0e0ddSKaricheri, Muralidharan #define XGBE_SS_REG_INDEX		0
8621e0e0ddSKaricheri, Muralidharan #define XGBE_SM_REG_INDEX		1
8721e0e0ddSKaricheri, Muralidharan #define XGBE_SERDES_REG_INDEX		2
8821e0e0ddSKaricheri, Muralidharan 
8921e0e0ddSKaricheri, Muralidharan /* offset relative to base of XGBE_SS_REG_INDEX */
9090cff9e2SWingman Kwok #define XGBE10_SGMII_MODULE_OFFSET	0x100
9121e0e0ddSKaricheri, Muralidharan /* offset relative to base of XGBE_SM_REG_INDEX */
9221e0e0ddSKaricheri, Muralidharan #define XGBE10_HOST_PORT_OFFSET		0x34
9321e0e0ddSKaricheri, Muralidharan #define XGBE10_SLAVE_PORT_OFFSET	0x64
9421e0e0ddSKaricheri, Muralidharan #define XGBE10_EMAC_OFFSET		0x400
9521e0e0ddSKaricheri, Muralidharan #define XGBE10_ALE_OFFSET		0x700
9621e0e0ddSKaricheri, Muralidharan #define XGBE10_HW_STATS_OFFSET		0x800
9790cff9e2SWingman Kwok #define XGBE10_HOST_PORT_NUM		0
9890cff9e2SWingman Kwok #define XGBE10_NUM_ALE_ENTRIES		1024
9990cff9e2SWingman Kwok 
1006f8d3f33SWingman Kwok #define	GBE_TIMER_INTERVAL			(HZ / 2)
1016f8d3f33SWingman Kwok 
1026f8d3f33SWingman Kwok /* Soft reset register values */
1036f8d3f33SWingman Kwok #define SOFT_RESET_MASK				BIT(0)
1046f8d3f33SWingman Kwok #define SOFT_RESET				BIT(0)
1056f8d3f33SWingman Kwok #define DEVICE_EMACSL_RESET_POLL_COUNT		100
1066f8d3f33SWingman Kwok #define GMACSL_RET_WARN_RESET_INCOMPLETE	-2
1076f8d3f33SWingman Kwok 
1086f8d3f33SWingman Kwok #define MACSL_RX_ENABLE_CSF			BIT(23)
1096f8d3f33SWingman Kwok #define MACSL_ENABLE_EXT_CTL			BIT(18)
11090cff9e2SWingman Kwok #define MACSL_XGMII_ENABLE			BIT(13)
11190cff9e2SWingman Kwok #define MACSL_XGIG_MODE				BIT(8)
1126f8d3f33SWingman Kwok #define MACSL_GIG_MODE				BIT(7)
1136f8d3f33SWingman Kwok #define MACSL_GMII_ENABLE			BIT(5)
1146f8d3f33SWingman Kwok #define MACSL_FULLDUPLEX			BIT(0)
1156f8d3f33SWingman Kwok 
1166f8d3f33SWingman Kwok #define GBE_CTL_P0_ENABLE			BIT(2)
1179a391c7bSWingMan Kwok #define GBE13_REG_VAL_STAT_ENABLE_ALL		0xff
11890cff9e2SWingman Kwok #define XGBE_REG_VAL_STAT_ENABLE_ALL		0xf
1196f8d3f33SWingman Kwok #define GBE_STATS_CD_SEL			BIT(28)
1206f8d3f33SWingman Kwok 
1216f8d3f33SWingman Kwok #define GBE_PORT_MASK(x)			(BIT(x) - 1)
1226f8d3f33SWingman Kwok #define GBE_MASK_NO_PORTS			0
1236f8d3f33SWingman Kwok 
1246f8d3f33SWingman Kwok #define GBE_DEF_1G_MAC_CONTROL					\
1256f8d3f33SWingman Kwok 		(MACSL_GIG_MODE | MACSL_GMII_ENABLE |		\
1266f8d3f33SWingman Kwok 		 MACSL_ENABLE_EXT_CTL |	MACSL_RX_ENABLE_CSF)
1276f8d3f33SWingman Kwok 
12890cff9e2SWingman Kwok #define GBE_DEF_10G_MAC_CONTROL				\
12990cff9e2SWingman Kwok 		(MACSL_XGIG_MODE | MACSL_XGMII_ENABLE |		\
13090cff9e2SWingman Kwok 		 MACSL_ENABLE_EXT_CTL |	MACSL_RX_ENABLE_CSF)
13190cff9e2SWingman Kwok 
1326f8d3f33SWingman Kwok #define GBE_STATSA_MODULE			0
1336f8d3f33SWingman Kwok #define GBE_STATSB_MODULE			1
1346f8d3f33SWingman Kwok #define GBE_STATSC_MODULE			2
1356f8d3f33SWingman Kwok #define GBE_STATSD_MODULE			3
1366f8d3f33SWingman Kwok 
1379a391c7bSWingMan Kwok #define GBENU_STATS0_MODULE			0
1389a391c7bSWingMan Kwok #define GBENU_STATS1_MODULE			1
1399a391c7bSWingMan Kwok #define GBENU_STATS2_MODULE			2
1409a391c7bSWingMan Kwok #define GBENU_STATS3_MODULE			3
1419a391c7bSWingMan Kwok #define GBENU_STATS4_MODULE			4
1429a391c7bSWingMan Kwok #define GBENU_STATS5_MODULE			5
1439a391c7bSWingMan Kwok #define GBENU_STATS6_MODULE			6
1449a391c7bSWingMan Kwok #define GBENU_STATS7_MODULE			7
1459a391c7bSWingMan Kwok #define GBENU_STATS8_MODULE			8
1469a391c7bSWingMan Kwok 
14790cff9e2SWingman Kwok #define XGBE_STATS0_MODULE			0
14890cff9e2SWingman Kwok #define XGBE_STATS1_MODULE			1
14990cff9e2SWingman Kwok #define XGBE_STATS2_MODULE			2
15090cff9e2SWingman Kwok 
1516f8d3f33SWingman Kwok /* s: 0-based slave_port */
1526f8d3f33SWingman Kwok #define SGMII_BASE(s) \
1536f8d3f33SWingman Kwok 	(((s) < 2) ? gbe_dev->sgmii_port_regs : gbe_dev->sgmii_port34_regs)
1546f8d3f33SWingman Kwok 
1556f8d3f33SWingman Kwok #define GBE_TX_QUEUE				648
1566f8d3f33SWingman Kwok #define	GBE_TXHOOK_ORDER			0
1576f8d3f33SWingman Kwok #define GBE_DEFAULT_ALE_AGEOUT			30
15890cff9e2SWingman Kwok #define SLAVE_LINK_IS_XGMII(s) ((s)->link_interface >= XGMII_LINK_MAC_PHY)
1596f8d3f33SWingman Kwok #define NETCP_LINK_STATE_INVALID		-1
1606f8d3f33SWingman Kwok 
1616f8d3f33SWingman Kwok #define GBE_SET_REG_OFS(p, rb, rn) p->rb##_ofs.rn = \
1626f8d3f33SWingman Kwok 		offsetof(struct gbe##_##rb, rn)
1639a391c7bSWingMan Kwok #define GBENU_SET_REG_OFS(p, rb, rn) p->rb##_ofs.rn = \
1649a391c7bSWingMan Kwok 		offsetof(struct gbenu##_##rb, rn)
16590cff9e2SWingman Kwok #define XGBE_SET_REG_OFS(p, rb, rn) p->rb##_ofs.rn = \
16690cff9e2SWingman Kwok 		offsetof(struct xgbe##_##rb, rn)
1676f8d3f33SWingman Kwok #define GBE_REG_ADDR(p, rb, rn) (p->rb + p->rb##_ofs.rn)
1686f8d3f33SWingman Kwok 
1699a391c7bSWingMan Kwok #define HOST_TX_PRI_MAP_DEFAULT			0x00000000
1709a391c7bSWingMan Kwok 
17190cff9e2SWingman Kwok struct xgbe_ss_regs {
17290cff9e2SWingman Kwok 	u32	id_ver;
17390cff9e2SWingman Kwok 	u32	synce_count;
17490cff9e2SWingman Kwok 	u32	synce_mux;
17590cff9e2SWingman Kwok 	u32	control;
17690cff9e2SWingman Kwok };
17790cff9e2SWingman Kwok 
17890cff9e2SWingman Kwok struct xgbe_switch_regs {
17990cff9e2SWingman Kwok 	u32	id_ver;
18090cff9e2SWingman Kwok 	u32	control;
18190cff9e2SWingman Kwok 	u32	emcontrol;
18290cff9e2SWingman Kwok 	u32	stat_port_en;
18390cff9e2SWingman Kwok 	u32	ptype;
18490cff9e2SWingman Kwok 	u32	soft_idle;
18590cff9e2SWingman Kwok 	u32	thru_rate;
18690cff9e2SWingman Kwok 	u32	gap_thresh;
18790cff9e2SWingman Kwok 	u32	tx_start_wds;
18890cff9e2SWingman Kwok 	u32	flow_control;
18990cff9e2SWingman Kwok 	u32	cppi_thresh;
19090cff9e2SWingman Kwok };
19190cff9e2SWingman Kwok 
19290cff9e2SWingman Kwok struct xgbe_port_regs {
19390cff9e2SWingman Kwok 	u32	blk_cnt;
19490cff9e2SWingman Kwok 	u32	port_vlan;
19590cff9e2SWingman Kwok 	u32	tx_pri_map;
19690cff9e2SWingman Kwok 	u32	sa_lo;
19790cff9e2SWingman Kwok 	u32	sa_hi;
19890cff9e2SWingman Kwok 	u32	ts_ctl;
19990cff9e2SWingman Kwok 	u32	ts_seq_ltype;
20090cff9e2SWingman Kwok 	u32	ts_vlan;
20190cff9e2SWingman Kwok 	u32	ts_ctl_ltype2;
20290cff9e2SWingman Kwok 	u32	ts_ctl2;
20390cff9e2SWingman Kwok 	u32	control;
20490cff9e2SWingman Kwok };
20590cff9e2SWingman Kwok 
20690cff9e2SWingman Kwok struct xgbe_host_port_regs {
20790cff9e2SWingman Kwok 	u32	blk_cnt;
20890cff9e2SWingman Kwok 	u32	port_vlan;
20990cff9e2SWingman Kwok 	u32	tx_pri_map;
21090cff9e2SWingman Kwok 	u32	src_id;
21190cff9e2SWingman Kwok 	u32	rx_pri_map;
21290cff9e2SWingman Kwok 	u32	rx_maxlen;
21390cff9e2SWingman Kwok };
21490cff9e2SWingman Kwok 
21590cff9e2SWingman Kwok struct xgbe_emac_regs {
21690cff9e2SWingman Kwok 	u32	id_ver;
21790cff9e2SWingman Kwok 	u32	mac_control;
21890cff9e2SWingman Kwok 	u32	mac_status;
21990cff9e2SWingman Kwok 	u32	soft_reset;
22090cff9e2SWingman Kwok 	u32	rx_maxlen;
22190cff9e2SWingman Kwok 	u32	__reserved_0;
22290cff9e2SWingman Kwok 	u32	rx_pause;
22390cff9e2SWingman Kwok 	u32	tx_pause;
22490cff9e2SWingman Kwok 	u32	em_control;
22590cff9e2SWingman Kwok 	u32	__reserved_1;
22690cff9e2SWingman Kwok 	u32	tx_gap;
22790cff9e2SWingman Kwok 	u32	rsvd[4];
22890cff9e2SWingman Kwok };
22990cff9e2SWingman Kwok 
23090cff9e2SWingman Kwok struct xgbe_host_hw_stats {
23190cff9e2SWingman Kwok 	u32	rx_good_frames;
23290cff9e2SWingman Kwok 	u32	rx_broadcast_frames;
23390cff9e2SWingman Kwok 	u32	rx_multicast_frames;
23490cff9e2SWingman Kwok 	u32	__rsvd_0[3];
23590cff9e2SWingman Kwok 	u32	rx_oversized_frames;
23690cff9e2SWingman Kwok 	u32	__rsvd_1;
23790cff9e2SWingman Kwok 	u32	rx_undersized_frames;
23890cff9e2SWingman Kwok 	u32	__rsvd_2;
23990cff9e2SWingman Kwok 	u32	overrun_type4;
24090cff9e2SWingman Kwok 	u32	overrun_type5;
24190cff9e2SWingman Kwok 	u32	rx_bytes;
24290cff9e2SWingman Kwok 	u32	tx_good_frames;
24390cff9e2SWingman Kwok 	u32	tx_broadcast_frames;
24490cff9e2SWingman Kwok 	u32	tx_multicast_frames;
24590cff9e2SWingman Kwok 	u32	__rsvd_3[9];
24690cff9e2SWingman Kwok 	u32	tx_bytes;
24790cff9e2SWingman Kwok 	u32	tx_64byte_frames;
24890cff9e2SWingman Kwok 	u32	tx_65_to_127byte_frames;
24990cff9e2SWingman Kwok 	u32	tx_128_to_255byte_frames;
25090cff9e2SWingman Kwok 	u32	tx_256_to_511byte_frames;
25190cff9e2SWingman Kwok 	u32	tx_512_to_1023byte_frames;
25290cff9e2SWingman Kwok 	u32	tx_1024byte_frames;
25390cff9e2SWingman Kwok 	u32	net_bytes;
25490cff9e2SWingman Kwok 	u32	rx_sof_overruns;
25590cff9e2SWingman Kwok 	u32	rx_mof_overruns;
25690cff9e2SWingman Kwok 	u32	rx_dma_overruns;
25790cff9e2SWingman Kwok };
25890cff9e2SWingman Kwok 
25990cff9e2SWingman Kwok struct xgbe_hw_stats {
26090cff9e2SWingman Kwok 	u32	rx_good_frames;
26190cff9e2SWingman Kwok 	u32	rx_broadcast_frames;
26290cff9e2SWingman Kwok 	u32	rx_multicast_frames;
26390cff9e2SWingman Kwok 	u32	rx_pause_frames;
26490cff9e2SWingman Kwok 	u32	rx_crc_errors;
26590cff9e2SWingman Kwok 	u32	rx_align_code_errors;
26690cff9e2SWingman Kwok 	u32	rx_oversized_frames;
26790cff9e2SWingman Kwok 	u32	rx_jabber_frames;
26890cff9e2SWingman Kwok 	u32	rx_undersized_frames;
26990cff9e2SWingman Kwok 	u32	rx_fragments;
27090cff9e2SWingman Kwok 	u32	overrun_type4;
27190cff9e2SWingman Kwok 	u32	overrun_type5;
27290cff9e2SWingman Kwok 	u32	rx_bytes;
27390cff9e2SWingman Kwok 	u32	tx_good_frames;
27490cff9e2SWingman Kwok 	u32	tx_broadcast_frames;
27590cff9e2SWingman Kwok 	u32	tx_multicast_frames;
27690cff9e2SWingman Kwok 	u32	tx_pause_frames;
27790cff9e2SWingman Kwok 	u32	tx_deferred_frames;
27890cff9e2SWingman Kwok 	u32	tx_collision_frames;
27990cff9e2SWingman Kwok 	u32	tx_single_coll_frames;
28090cff9e2SWingman Kwok 	u32	tx_mult_coll_frames;
28190cff9e2SWingman Kwok 	u32	tx_excessive_collisions;
28290cff9e2SWingman Kwok 	u32	tx_late_collisions;
28390cff9e2SWingman Kwok 	u32	tx_underrun;
28490cff9e2SWingman Kwok 	u32	tx_carrier_sense_errors;
28590cff9e2SWingman Kwok 	u32	tx_bytes;
28690cff9e2SWingman Kwok 	u32	tx_64byte_frames;
28790cff9e2SWingman Kwok 	u32	tx_65_to_127byte_frames;
28890cff9e2SWingman Kwok 	u32	tx_128_to_255byte_frames;
28990cff9e2SWingman Kwok 	u32	tx_256_to_511byte_frames;
29090cff9e2SWingman Kwok 	u32	tx_512_to_1023byte_frames;
29190cff9e2SWingman Kwok 	u32	tx_1024byte_frames;
29290cff9e2SWingman Kwok 	u32	net_bytes;
29390cff9e2SWingman Kwok 	u32	rx_sof_overruns;
29490cff9e2SWingman Kwok 	u32	rx_mof_overruns;
29590cff9e2SWingman Kwok 	u32	rx_dma_overruns;
29690cff9e2SWingman Kwok };
29790cff9e2SWingman Kwok 
2989a391c7bSWingMan Kwok struct gbenu_ss_regs {
2999a391c7bSWingMan Kwok 	u32	id_ver;
3009a391c7bSWingMan Kwok 	u32	synce_count;		/* NU */
3019a391c7bSWingMan Kwok 	u32	synce_mux;		/* NU */
3029a391c7bSWingMan Kwok 	u32	control;		/* 2U */
3039a391c7bSWingMan Kwok 	u32	__rsvd_0[2];		/* 2U */
3049a391c7bSWingMan Kwok 	u32	rgmii_status;		/* 2U */
3059a391c7bSWingMan Kwok 	u32	ss_status;		/* 2U */
3069a391c7bSWingMan Kwok };
3079a391c7bSWingMan Kwok 
3089a391c7bSWingMan Kwok struct gbenu_switch_regs {
3099a391c7bSWingMan Kwok 	u32	id_ver;
3109a391c7bSWingMan Kwok 	u32	control;
3119a391c7bSWingMan Kwok 	u32	__rsvd_0[2];
3129a391c7bSWingMan Kwok 	u32	emcontrol;
3139a391c7bSWingMan Kwok 	u32	stat_port_en;
3149a391c7bSWingMan Kwok 	u32	ptype;			/* NU */
3159a391c7bSWingMan Kwok 	u32	soft_idle;
3169a391c7bSWingMan Kwok 	u32	thru_rate;		/* NU */
3179a391c7bSWingMan Kwok 	u32	gap_thresh;		/* NU */
3189a391c7bSWingMan Kwok 	u32	tx_start_wds;		/* NU */
3199a391c7bSWingMan Kwok 	u32	eee_prescale;		/* 2U */
3209a391c7bSWingMan Kwok 	u32	tx_g_oflow_thresh_set;	/* NU */
3219a391c7bSWingMan Kwok 	u32	tx_g_oflow_thresh_clr;	/* NU */
3229a391c7bSWingMan Kwok 	u32	tx_g_buf_thresh_set_l;	/* NU */
3239a391c7bSWingMan Kwok 	u32	tx_g_buf_thresh_set_h;	/* NU */
3249a391c7bSWingMan Kwok 	u32	tx_g_buf_thresh_clr_l;	/* NU */
3259a391c7bSWingMan Kwok 	u32	tx_g_buf_thresh_clr_h;	/* NU */
3269a391c7bSWingMan Kwok };
3279a391c7bSWingMan Kwok 
3289a391c7bSWingMan Kwok struct gbenu_port_regs {
3299a391c7bSWingMan Kwok 	u32	__rsvd_0;
3309a391c7bSWingMan Kwok 	u32	control;
3319a391c7bSWingMan Kwok 	u32	max_blks;		/* 2U */
3329a391c7bSWingMan Kwok 	u32	mem_align1;
3339a391c7bSWingMan Kwok 	u32	blk_cnt;
3349a391c7bSWingMan Kwok 	u32	port_vlan;
3359a391c7bSWingMan Kwok 	u32	tx_pri_map;		/* NU */
3369a391c7bSWingMan Kwok 	u32	pri_ctl;		/* 2U */
3379a391c7bSWingMan Kwok 	u32	rx_pri_map;
3389a391c7bSWingMan Kwok 	u32	rx_maxlen;
3399a391c7bSWingMan Kwok 	u32	tx_blks_pri;		/* NU */
3409a391c7bSWingMan Kwok 	u32	__rsvd_1;
3419a391c7bSWingMan Kwok 	u32	idle2lpi;		/* 2U */
3429a391c7bSWingMan Kwok 	u32	lpi2idle;		/* 2U */
3439a391c7bSWingMan Kwok 	u32	eee_status;		/* 2U */
3449a391c7bSWingMan Kwok 	u32	__rsvd_2;
3459a391c7bSWingMan Kwok 	u32	__rsvd_3[176];		/* NU: more to add */
3469a391c7bSWingMan Kwok 	u32	__rsvd_4[2];
3479a391c7bSWingMan Kwok 	u32	sa_lo;
3489a391c7bSWingMan Kwok 	u32	sa_hi;
3499a391c7bSWingMan Kwok 	u32	ts_ctl;
3509a391c7bSWingMan Kwok 	u32	ts_seq_ltype;
3519a391c7bSWingMan Kwok 	u32	ts_vlan;
3529a391c7bSWingMan Kwok 	u32	ts_ctl_ltype2;
3539a391c7bSWingMan Kwok 	u32	ts_ctl2;
3549a391c7bSWingMan Kwok };
3559a391c7bSWingMan Kwok 
3569a391c7bSWingMan Kwok struct gbenu_host_port_regs {
3579a391c7bSWingMan Kwok 	u32	__rsvd_0;
3589a391c7bSWingMan Kwok 	u32	control;
3599a391c7bSWingMan Kwok 	u32	flow_id_offset;		/* 2U */
3609a391c7bSWingMan Kwok 	u32	__rsvd_1;
3619a391c7bSWingMan Kwok 	u32	blk_cnt;
3629a391c7bSWingMan Kwok 	u32	port_vlan;
3639a391c7bSWingMan Kwok 	u32	tx_pri_map;		/* NU */
3649a391c7bSWingMan Kwok 	u32	pri_ctl;
3659a391c7bSWingMan Kwok 	u32	rx_pri_map;
3669a391c7bSWingMan Kwok 	u32	rx_maxlen;
3679a391c7bSWingMan Kwok 	u32	tx_blks_pri;		/* NU */
3689a391c7bSWingMan Kwok 	u32	__rsvd_2;
3699a391c7bSWingMan Kwok 	u32	idle2lpi;		/* 2U */
3709a391c7bSWingMan Kwok 	u32	lpi2wake;		/* 2U */
3719a391c7bSWingMan Kwok 	u32	eee_status;		/* 2U */
3729a391c7bSWingMan Kwok 	u32	__rsvd_3;
3739a391c7bSWingMan Kwok 	u32	__rsvd_4[184];		/* NU */
3749a391c7bSWingMan Kwok 	u32	host_blks_pri;		/* NU */
3759a391c7bSWingMan Kwok };
3769a391c7bSWingMan Kwok 
3779a391c7bSWingMan Kwok struct gbenu_emac_regs {
3789a391c7bSWingMan Kwok 	u32	mac_control;
3799a391c7bSWingMan Kwok 	u32	mac_status;
3809a391c7bSWingMan Kwok 	u32	soft_reset;
3819a391c7bSWingMan Kwok 	u32	boff_test;
3829a391c7bSWingMan Kwok 	u32	rx_pause;
3839a391c7bSWingMan Kwok 	u32	__rsvd_0[11];		/* NU */
3849a391c7bSWingMan Kwok 	u32	tx_pause;
3859a391c7bSWingMan Kwok 	u32	__rsvd_1[11];		/* NU */
3869a391c7bSWingMan Kwok 	u32	em_control;
3879a391c7bSWingMan Kwok 	u32	tx_gap;
3889a391c7bSWingMan Kwok };
3899a391c7bSWingMan Kwok 
3909a391c7bSWingMan Kwok /* Some hw stat regs are applicable to slave port only.
3919a391c7bSWingMan Kwok  * This is handled by gbenu_et_stats struct.  Also some
3929a391c7bSWingMan Kwok  * are for SS version NU and some are for 2U.
3939a391c7bSWingMan Kwok  */
3949a391c7bSWingMan Kwok struct gbenu_hw_stats {
3959a391c7bSWingMan Kwok 	u32	rx_good_frames;
3969a391c7bSWingMan Kwok 	u32	rx_broadcast_frames;
3979a391c7bSWingMan Kwok 	u32	rx_multicast_frames;
3989a391c7bSWingMan Kwok 	u32	rx_pause_frames;		/* slave */
3999a391c7bSWingMan Kwok 	u32	rx_crc_errors;
4009a391c7bSWingMan Kwok 	u32	rx_align_code_errors;		/* slave */
4019a391c7bSWingMan Kwok 	u32	rx_oversized_frames;
4029a391c7bSWingMan Kwok 	u32	rx_jabber_frames;		/* slave */
4039a391c7bSWingMan Kwok 	u32	rx_undersized_frames;
4049a391c7bSWingMan Kwok 	u32	rx_fragments;			/* slave */
4059a391c7bSWingMan Kwok 	u32	ale_drop;
4069a391c7bSWingMan Kwok 	u32	ale_overrun_drop;
4079a391c7bSWingMan Kwok 	u32	rx_bytes;
4089a391c7bSWingMan Kwok 	u32	tx_good_frames;
4099a391c7bSWingMan Kwok 	u32	tx_broadcast_frames;
4109a391c7bSWingMan Kwok 	u32	tx_multicast_frames;
4119a391c7bSWingMan Kwok 	u32	tx_pause_frames;		/* slave */
4129a391c7bSWingMan Kwok 	u32	tx_deferred_frames;		/* slave */
4139a391c7bSWingMan Kwok 	u32	tx_collision_frames;		/* slave */
4149a391c7bSWingMan Kwok 	u32	tx_single_coll_frames;		/* slave */
4159a391c7bSWingMan Kwok 	u32	tx_mult_coll_frames;		/* slave */
4169a391c7bSWingMan Kwok 	u32	tx_excessive_collisions;	/* slave */
4179a391c7bSWingMan Kwok 	u32	tx_late_collisions;		/* slave */
4189a391c7bSWingMan Kwok 	u32	rx_ipg_error;			/* slave 10G only */
4199a391c7bSWingMan Kwok 	u32	tx_carrier_sense_errors;	/* slave */
4209a391c7bSWingMan Kwok 	u32	tx_bytes;
4219a391c7bSWingMan Kwok 	u32	tx_64B_frames;
4229a391c7bSWingMan Kwok 	u32	tx_65_to_127B_frames;
4239a391c7bSWingMan Kwok 	u32	tx_128_to_255B_frames;
4249a391c7bSWingMan Kwok 	u32	tx_256_to_511B_frames;
4259a391c7bSWingMan Kwok 	u32	tx_512_to_1023B_frames;
4269a391c7bSWingMan Kwok 	u32	tx_1024B_frames;
4279a391c7bSWingMan Kwok 	u32	net_bytes;
4289a391c7bSWingMan Kwok 	u32	rx_bottom_fifo_drop;
4299a391c7bSWingMan Kwok 	u32	rx_port_mask_drop;
4309a391c7bSWingMan Kwok 	u32	rx_top_fifo_drop;
4319a391c7bSWingMan Kwok 	u32	ale_rate_limit_drop;
4329a391c7bSWingMan Kwok 	u32	ale_vid_ingress_drop;
4339a391c7bSWingMan Kwok 	u32	ale_da_eq_sa_drop;
4349a391c7bSWingMan Kwok 	u32	__rsvd_0[3];
4359a391c7bSWingMan Kwok 	u32	ale_unknown_ucast;
4369a391c7bSWingMan Kwok 	u32	ale_unknown_ucast_bytes;
4379a391c7bSWingMan Kwok 	u32	ale_unknown_mcast;
4389a391c7bSWingMan Kwok 	u32	ale_unknown_mcast_bytes;
4399a391c7bSWingMan Kwok 	u32	ale_unknown_bcast;
4409a391c7bSWingMan Kwok 	u32	ale_unknown_bcast_bytes;
4419a391c7bSWingMan Kwok 	u32	ale_pol_match;
4429a391c7bSWingMan Kwok 	u32	ale_pol_match_red;		/* NU */
4439a391c7bSWingMan Kwok 	u32	ale_pol_match_yellow;		/* NU */
4449a391c7bSWingMan Kwok 	u32	__rsvd_1[44];
4459a391c7bSWingMan Kwok 	u32	tx_mem_protect_err;
4469a391c7bSWingMan Kwok 	/* following NU only */
4479a391c7bSWingMan Kwok 	u32	tx_pri0;
4489a391c7bSWingMan Kwok 	u32	tx_pri1;
4499a391c7bSWingMan Kwok 	u32	tx_pri2;
4509a391c7bSWingMan Kwok 	u32	tx_pri3;
4519a391c7bSWingMan Kwok 	u32	tx_pri4;
4529a391c7bSWingMan Kwok 	u32	tx_pri5;
4539a391c7bSWingMan Kwok 	u32	tx_pri6;
4549a391c7bSWingMan Kwok 	u32	tx_pri7;
4559a391c7bSWingMan Kwok 	u32	tx_pri0_bcnt;
4569a391c7bSWingMan Kwok 	u32	tx_pri1_bcnt;
4579a391c7bSWingMan Kwok 	u32	tx_pri2_bcnt;
4589a391c7bSWingMan Kwok 	u32	tx_pri3_bcnt;
4599a391c7bSWingMan Kwok 	u32	tx_pri4_bcnt;
4609a391c7bSWingMan Kwok 	u32	tx_pri5_bcnt;
4619a391c7bSWingMan Kwok 	u32	tx_pri6_bcnt;
4629a391c7bSWingMan Kwok 	u32	tx_pri7_bcnt;
4639a391c7bSWingMan Kwok 	u32	tx_pri0_drop;
4649a391c7bSWingMan Kwok 	u32	tx_pri1_drop;
4659a391c7bSWingMan Kwok 	u32	tx_pri2_drop;
4669a391c7bSWingMan Kwok 	u32	tx_pri3_drop;
4679a391c7bSWingMan Kwok 	u32	tx_pri4_drop;
4689a391c7bSWingMan Kwok 	u32	tx_pri5_drop;
4699a391c7bSWingMan Kwok 	u32	tx_pri6_drop;
4709a391c7bSWingMan Kwok 	u32	tx_pri7_drop;
4719a391c7bSWingMan Kwok 	u32	tx_pri0_drop_bcnt;
4729a391c7bSWingMan Kwok 	u32	tx_pri1_drop_bcnt;
4739a391c7bSWingMan Kwok 	u32	tx_pri2_drop_bcnt;
4749a391c7bSWingMan Kwok 	u32	tx_pri3_drop_bcnt;
4759a391c7bSWingMan Kwok 	u32	tx_pri4_drop_bcnt;
4769a391c7bSWingMan Kwok 	u32	tx_pri5_drop_bcnt;
4779a391c7bSWingMan Kwok 	u32	tx_pri6_drop_bcnt;
4789a391c7bSWingMan Kwok 	u32	tx_pri7_drop_bcnt;
4799a391c7bSWingMan Kwok };
4809a391c7bSWingMan Kwok 
4819a391c7bSWingMan Kwok #define GBENU_HW_STATS_REG_MAP_SZ	0x200
4829a391c7bSWingMan Kwok 
4836f8d3f33SWingman Kwok struct gbe_ss_regs {
4846f8d3f33SWingman Kwok 	u32	id_ver;
4856f8d3f33SWingman Kwok 	u32	synce_count;
4866f8d3f33SWingman Kwok 	u32	synce_mux;
4876f8d3f33SWingman Kwok };
4886f8d3f33SWingman Kwok 
4896f8d3f33SWingman Kwok struct gbe_ss_regs_ofs {
4906f8d3f33SWingman Kwok 	u16	id_ver;
4916f8d3f33SWingman Kwok 	u16	control;
4926f8d3f33SWingman Kwok };
4936f8d3f33SWingman Kwok 
4946f8d3f33SWingman Kwok struct gbe_switch_regs {
4956f8d3f33SWingman Kwok 	u32	id_ver;
4966f8d3f33SWingman Kwok 	u32	control;
4976f8d3f33SWingman Kwok 	u32	soft_reset;
4986f8d3f33SWingman Kwok 	u32	stat_port_en;
4996f8d3f33SWingman Kwok 	u32	ptype;
5006f8d3f33SWingman Kwok 	u32	soft_idle;
5016f8d3f33SWingman Kwok 	u32	thru_rate;
5026f8d3f33SWingman Kwok 	u32	gap_thresh;
5036f8d3f33SWingman Kwok 	u32	tx_start_wds;
5046f8d3f33SWingman Kwok 	u32	flow_control;
5056f8d3f33SWingman Kwok };
5066f8d3f33SWingman Kwok 
5076f8d3f33SWingman Kwok struct gbe_switch_regs_ofs {
5086f8d3f33SWingman Kwok 	u16	id_ver;
5096f8d3f33SWingman Kwok 	u16	control;
5106f8d3f33SWingman Kwok 	u16	soft_reset;
5116f8d3f33SWingman Kwok 	u16	emcontrol;
5126f8d3f33SWingman Kwok 	u16	stat_port_en;
5136f8d3f33SWingman Kwok 	u16	ptype;
5146f8d3f33SWingman Kwok 	u16	flow_control;
5156f8d3f33SWingman Kwok };
5166f8d3f33SWingman Kwok 
5176f8d3f33SWingman Kwok struct gbe_port_regs {
5186f8d3f33SWingman Kwok 	u32	max_blks;
5196f8d3f33SWingman Kwok 	u32	blk_cnt;
5206f8d3f33SWingman Kwok 	u32	port_vlan;
5216f8d3f33SWingman Kwok 	u32	tx_pri_map;
5226f8d3f33SWingman Kwok 	u32	sa_lo;
5236f8d3f33SWingman Kwok 	u32	sa_hi;
5246f8d3f33SWingman Kwok 	u32	ts_ctl;
5256f8d3f33SWingman Kwok 	u32	ts_seq_ltype;
5266f8d3f33SWingman Kwok 	u32	ts_vlan;
5276f8d3f33SWingman Kwok 	u32	ts_ctl_ltype2;
5286f8d3f33SWingman Kwok 	u32	ts_ctl2;
5296f8d3f33SWingman Kwok };
5306f8d3f33SWingman Kwok 
5316f8d3f33SWingman Kwok struct gbe_port_regs_ofs {
5326f8d3f33SWingman Kwok 	u16	port_vlan;
5336f8d3f33SWingman Kwok 	u16	tx_pri_map;
5346f8d3f33SWingman Kwok 	u16	sa_lo;
5356f8d3f33SWingman Kwok 	u16	sa_hi;
5366f8d3f33SWingman Kwok 	u16	ts_ctl;
5376f8d3f33SWingman Kwok 	u16	ts_seq_ltype;
5386f8d3f33SWingman Kwok 	u16	ts_vlan;
5396f8d3f33SWingman Kwok 	u16	ts_ctl_ltype2;
5406f8d3f33SWingman Kwok 	u16	ts_ctl2;
5419a391c7bSWingMan Kwok 	u16	rx_maxlen;	/* 2U, NU */
5426f8d3f33SWingman Kwok };
5436f8d3f33SWingman Kwok 
5446f8d3f33SWingman Kwok struct gbe_host_port_regs {
5456f8d3f33SWingman Kwok 	u32	src_id;
5466f8d3f33SWingman Kwok 	u32	port_vlan;
5476f8d3f33SWingman Kwok 	u32	rx_pri_map;
5486f8d3f33SWingman Kwok 	u32	rx_maxlen;
5496f8d3f33SWingman Kwok };
5506f8d3f33SWingman Kwok 
5516f8d3f33SWingman Kwok struct gbe_host_port_regs_ofs {
5526f8d3f33SWingman Kwok 	u16	port_vlan;
5536f8d3f33SWingman Kwok 	u16	tx_pri_map;
5546f8d3f33SWingman Kwok 	u16	rx_maxlen;
5556f8d3f33SWingman Kwok };
5566f8d3f33SWingman Kwok 
5576f8d3f33SWingman Kwok struct gbe_emac_regs {
5586f8d3f33SWingman Kwok 	u32	id_ver;
5596f8d3f33SWingman Kwok 	u32	mac_control;
5606f8d3f33SWingman Kwok 	u32	mac_status;
5616f8d3f33SWingman Kwok 	u32	soft_reset;
5626f8d3f33SWingman Kwok 	u32	rx_maxlen;
5636f8d3f33SWingman Kwok 	u32	__reserved_0;
5646f8d3f33SWingman Kwok 	u32	rx_pause;
5656f8d3f33SWingman Kwok 	u32	tx_pause;
5666f8d3f33SWingman Kwok 	u32	__reserved_1;
5676f8d3f33SWingman Kwok 	u32	rx_pri_map;
5686f8d3f33SWingman Kwok 	u32	rsvd[6];
5696f8d3f33SWingman Kwok };
5706f8d3f33SWingman Kwok 
5716f8d3f33SWingman Kwok struct gbe_emac_regs_ofs {
5726f8d3f33SWingman Kwok 	u16	mac_control;
5736f8d3f33SWingman Kwok 	u16	soft_reset;
5746f8d3f33SWingman Kwok 	u16	rx_maxlen;
5756f8d3f33SWingman Kwok };
5766f8d3f33SWingman Kwok 
5776f8d3f33SWingman Kwok struct gbe_hw_stats {
5786f8d3f33SWingman Kwok 	u32	rx_good_frames;
5796f8d3f33SWingman Kwok 	u32	rx_broadcast_frames;
5806f8d3f33SWingman Kwok 	u32	rx_multicast_frames;
5816f8d3f33SWingman Kwok 	u32	rx_pause_frames;
5826f8d3f33SWingman Kwok 	u32	rx_crc_errors;
5836f8d3f33SWingman Kwok 	u32	rx_align_code_errors;
5846f8d3f33SWingman Kwok 	u32	rx_oversized_frames;
5856f8d3f33SWingman Kwok 	u32	rx_jabber_frames;
5866f8d3f33SWingman Kwok 	u32	rx_undersized_frames;
5876f8d3f33SWingman Kwok 	u32	rx_fragments;
5886f8d3f33SWingman Kwok 	u32	__pad_0[2];
5896f8d3f33SWingman Kwok 	u32	rx_bytes;
5906f8d3f33SWingman Kwok 	u32	tx_good_frames;
5916f8d3f33SWingman Kwok 	u32	tx_broadcast_frames;
5926f8d3f33SWingman Kwok 	u32	tx_multicast_frames;
5936f8d3f33SWingman Kwok 	u32	tx_pause_frames;
5946f8d3f33SWingman Kwok 	u32	tx_deferred_frames;
5956f8d3f33SWingman Kwok 	u32	tx_collision_frames;
5966f8d3f33SWingman Kwok 	u32	tx_single_coll_frames;
5976f8d3f33SWingman Kwok 	u32	tx_mult_coll_frames;
5986f8d3f33SWingman Kwok 	u32	tx_excessive_collisions;
5996f8d3f33SWingman Kwok 	u32	tx_late_collisions;
6006f8d3f33SWingman Kwok 	u32	tx_underrun;
6016f8d3f33SWingman Kwok 	u32	tx_carrier_sense_errors;
6026f8d3f33SWingman Kwok 	u32	tx_bytes;
6036f8d3f33SWingman Kwok 	u32	tx_64byte_frames;
6046f8d3f33SWingman Kwok 	u32	tx_65_to_127byte_frames;
6056f8d3f33SWingman Kwok 	u32	tx_128_to_255byte_frames;
6066f8d3f33SWingman Kwok 	u32	tx_256_to_511byte_frames;
6076f8d3f33SWingman Kwok 	u32	tx_512_to_1023byte_frames;
6086f8d3f33SWingman Kwok 	u32	tx_1024byte_frames;
6096f8d3f33SWingman Kwok 	u32	net_bytes;
6106f8d3f33SWingman Kwok 	u32	rx_sof_overruns;
6116f8d3f33SWingman Kwok 	u32	rx_mof_overruns;
6126f8d3f33SWingman Kwok 	u32	rx_dma_overruns;
6136f8d3f33SWingman Kwok };
6146f8d3f33SWingman Kwok 
6159a391c7bSWingMan Kwok #define GBE_MAX_HW_STAT_MODS			9
6166f8d3f33SWingman Kwok #define GBE_HW_STATS_REG_MAP_SZ			0x100
6176f8d3f33SWingman Kwok 
6186f8d3f33SWingman Kwok struct gbe_slave {
6196f8d3f33SWingman Kwok 	void __iomem			*port_regs;
6206f8d3f33SWingman Kwok 	void __iomem			*emac_regs;
6216f8d3f33SWingman Kwok 	struct gbe_port_regs_ofs	port_regs_ofs;
6226f8d3f33SWingman Kwok 	struct gbe_emac_regs_ofs	emac_regs_ofs;
6236f8d3f33SWingman Kwok 	int				slave_num; /* 0 based logical number */
6246f8d3f33SWingman Kwok 	int				port_num;  /* actual port number */
6256f8d3f33SWingman Kwok 	atomic_t			link_state;
6266f8d3f33SWingman Kwok 	bool				open;
6276f8d3f33SWingman Kwok 	struct phy_device		*phy;
6286f8d3f33SWingman Kwok 	u32				link_interface;
6296f8d3f33SWingman Kwok 	u32				mac_control;
6306f8d3f33SWingman Kwok 	u8				phy_port_t;
6316f8d3f33SWingman Kwok 	struct device_node		*phy_node;
6326f8d3f33SWingman Kwok 	struct list_head		slave_list;
6336f8d3f33SWingman Kwok };
6346f8d3f33SWingman Kwok 
6356f8d3f33SWingman Kwok struct gbe_priv {
6366f8d3f33SWingman Kwok 	struct device			*dev;
6376f8d3f33SWingman Kwok 	struct netcp_device		*netcp_device;
6386f8d3f33SWingman Kwok 	struct timer_list		timer;
6396f8d3f33SWingman Kwok 	u32				num_slaves;
6406f8d3f33SWingman Kwok 	u32				ale_entries;
6416f8d3f33SWingman Kwok 	u32				ale_ports;
6426f8d3f33SWingman Kwok 	bool				enable_ale;
6439a391c7bSWingMan Kwok 	u8				max_num_slaves;
6449a391c7bSWingMan Kwok 	u8				max_num_ports; /* max_num_slaves + 1 */
645489e8a2fSWingMan Kwok 	u8				num_stats_mods;
6466f8d3f33SWingman Kwok 	struct netcp_tx_pipe		tx_pipe;
6476f8d3f33SWingman Kwok 
6486f8d3f33SWingman Kwok 	int				host_port;
6496f8d3f33SWingman Kwok 	u32				rx_packet_max;
6506f8d3f33SWingman Kwok 	u32				ss_version;
6519a391c7bSWingMan Kwok 	u32				stats_en_mask;
6526f8d3f33SWingman Kwok 
6536f8d3f33SWingman Kwok 	void __iomem			*ss_regs;
6546f8d3f33SWingman Kwok 	void __iomem			*switch_regs;
6556f8d3f33SWingman Kwok 	void __iomem			*host_port_regs;
6566f8d3f33SWingman Kwok 	void __iomem			*ale_reg;
6576f8d3f33SWingman Kwok 	void __iomem			*sgmii_port_regs;
6586f8d3f33SWingman Kwok 	void __iomem			*sgmii_port34_regs;
6596f8d3f33SWingman Kwok 	void __iomem			*xgbe_serdes_regs;
6606f8d3f33SWingman Kwok 	void __iomem			*hw_stats_regs[GBE_MAX_HW_STAT_MODS];
6616f8d3f33SWingman Kwok 
6626f8d3f33SWingman Kwok 	struct gbe_ss_regs_ofs		ss_regs_ofs;
6636f8d3f33SWingman Kwok 	struct gbe_switch_regs_ofs	switch_regs_ofs;
6646f8d3f33SWingman Kwok 	struct gbe_host_port_regs_ofs	host_port_regs_ofs;
6656f8d3f33SWingman Kwok 
6666f8d3f33SWingman Kwok 	struct cpsw_ale			*ale;
6676f8d3f33SWingman Kwok 	unsigned int			tx_queue_id;
6686f8d3f33SWingman Kwok 	const char			*dma_chan_name;
6696f8d3f33SWingman Kwok 
6706f8d3f33SWingman Kwok 	struct list_head		gbe_intf_head;
6716f8d3f33SWingman Kwok 	struct list_head		secondary_slaves;
6726f8d3f33SWingman Kwok 	struct net_device		*dummy_ndev;
6736f8d3f33SWingman Kwok 
6746f8d3f33SWingman Kwok 	u64				*hw_stats;
675489e8a2fSWingMan Kwok 	u32				*hw_stats_prev;
6766f8d3f33SWingman Kwok 	const struct netcp_ethtool_stat *et_stats;
6776f8d3f33SWingman Kwok 	int				num_et_stats;
6786f8d3f33SWingman Kwok 	/*  Lock for updating the hwstats */
6796f8d3f33SWingman Kwok 	spinlock_t			hw_stats_lock;
6806f8d3f33SWingman Kwok };
6816f8d3f33SWingman Kwok 
6826f8d3f33SWingman Kwok struct gbe_intf {
6836f8d3f33SWingman Kwok 	struct net_device	*ndev;
6846f8d3f33SWingman Kwok 	struct device		*dev;
6856f8d3f33SWingman Kwok 	struct gbe_priv		*gbe_dev;
6866f8d3f33SWingman Kwok 	struct netcp_tx_pipe	tx_pipe;
6876f8d3f33SWingman Kwok 	struct gbe_slave	*slave;
6886f8d3f33SWingman Kwok 	struct list_head	gbe_intf_list;
6896f8d3f33SWingman Kwok 	unsigned long		active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
6906f8d3f33SWingman Kwok };
6916f8d3f33SWingman Kwok 
6926f8d3f33SWingman Kwok static struct netcp_module gbe_module;
69390cff9e2SWingman Kwok static struct netcp_module xgbe_module;
6946f8d3f33SWingman Kwok 
6956f8d3f33SWingman Kwok /* Statistic management */
6966f8d3f33SWingman Kwok struct netcp_ethtool_stat {
6976f8d3f33SWingman Kwok 	char desc[ETH_GSTRING_LEN];
6986f8d3f33SWingman Kwok 	int type;
6996f8d3f33SWingman Kwok 	u32 size;
7006f8d3f33SWingman Kwok 	int offset;
7016f8d3f33SWingman Kwok };
7026f8d3f33SWingman Kwok 
703da866ba0SKaricheri, Muralidharan #define GBE_STATSA_INFO(field)						\
704da866ba0SKaricheri, Muralidharan {									\
705da866ba0SKaricheri, Muralidharan 	"GBE_A:"#field, GBE_STATSA_MODULE,				\
7066f8d3f33SWingman Kwok 	FIELD_SIZEOF(struct gbe_hw_stats, field),			\
707da866ba0SKaricheri, Muralidharan 	offsetof(struct gbe_hw_stats, field)				\
708da866ba0SKaricheri, Muralidharan }
7096f8d3f33SWingman Kwok 
710da866ba0SKaricheri, Muralidharan #define GBE_STATSB_INFO(field)						\
711da866ba0SKaricheri, Muralidharan {									\
712da866ba0SKaricheri, Muralidharan 	"GBE_B:"#field, GBE_STATSB_MODULE,				\
7136f8d3f33SWingman Kwok 	FIELD_SIZEOF(struct gbe_hw_stats, field),			\
714da866ba0SKaricheri, Muralidharan 	offsetof(struct gbe_hw_stats, field)				\
715da866ba0SKaricheri, Muralidharan }
7166f8d3f33SWingman Kwok 
717da866ba0SKaricheri, Muralidharan #define GBE_STATSC_INFO(field)						\
718da866ba0SKaricheri, Muralidharan {									\
719da866ba0SKaricheri, Muralidharan 	"GBE_C:"#field, GBE_STATSC_MODULE,				\
7206f8d3f33SWingman Kwok 	FIELD_SIZEOF(struct gbe_hw_stats, field),			\
721da866ba0SKaricheri, Muralidharan 	offsetof(struct gbe_hw_stats, field)				\
722da866ba0SKaricheri, Muralidharan }
7236f8d3f33SWingman Kwok 
724da866ba0SKaricheri, Muralidharan #define GBE_STATSD_INFO(field)						\
725da866ba0SKaricheri, Muralidharan {									\
726da866ba0SKaricheri, Muralidharan 	"GBE_D:"#field, GBE_STATSD_MODULE,				\
7276f8d3f33SWingman Kwok 	FIELD_SIZEOF(struct gbe_hw_stats, field),			\
728da866ba0SKaricheri, Muralidharan 	offsetof(struct gbe_hw_stats, field)				\
729da866ba0SKaricheri, Muralidharan }
7306f8d3f33SWingman Kwok 
7316f8d3f33SWingman Kwok static const struct netcp_ethtool_stat gbe13_et_stats[] = {
7326f8d3f33SWingman Kwok 	/* GBE module A */
733da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(rx_good_frames),
734da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(rx_broadcast_frames),
735da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(rx_multicast_frames),
736da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(rx_pause_frames),
737da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(rx_crc_errors),
738da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(rx_align_code_errors),
739da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(rx_oversized_frames),
740da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(rx_jabber_frames),
741da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(rx_undersized_frames),
742da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(rx_fragments),
743da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(rx_bytes),
744da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(tx_good_frames),
745da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(tx_broadcast_frames),
746da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(tx_multicast_frames),
747da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(tx_pause_frames),
748da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(tx_deferred_frames),
749da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(tx_collision_frames),
750da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(tx_single_coll_frames),
751da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(tx_mult_coll_frames),
752da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(tx_excessive_collisions),
753da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(tx_late_collisions),
754da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(tx_underrun),
755da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(tx_carrier_sense_errors),
756da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(tx_bytes),
757da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(tx_64byte_frames),
758da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(tx_65_to_127byte_frames),
759da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(tx_128_to_255byte_frames),
760da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(tx_256_to_511byte_frames),
761da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(tx_512_to_1023byte_frames),
762da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(tx_1024byte_frames),
763da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(net_bytes),
764da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(rx_sof_overruns),
765da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(rx_mof_overruns),
766da866ba0SKaricheri, Muralidharan 	GBE_STATSA_INFO(rx_dma_overruns),
7676f8d3f33SWingman Kwok 	/* GBE module B */
768da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(rx_good_frames),
769da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(rx_broadcast_frames),
770da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(rx_multicast_frames),
771da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(rx_pause_frames),
772da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(rx_crc_errors),
773da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(rx_align_code_errors),
774da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(rx_oversized_frames),
775da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(rx_jabber_frames),
776da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(rx_undersized_frames),
777da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(rx_fragments),
778da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(rx_bytes),
779da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(tx_good_frames),
780da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(tx_broadcast_frames),
781da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(tx_multicast_frames),
782da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(tx_pause_frames),
783da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(tx_deferred_frames),
784da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(tx_collision_frames),
785da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(tx_single_coll_frames),
786da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(tx_mult_coll_frames),
787da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(tx_excessive_collisions),
788da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(tx_late_collisions),
789da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(tx_underrun),
790da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(tx_carrier_sense_errors),
791da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(tx_bytes),
792da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(tx_64byte_frames),
793da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(tx_65_to_127byte_frames),
794da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(tx_128_to_255byte_frames),
795da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(tx_256_to_511byte_frames),
796da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(tx_512_to_1023byte_frames),
797da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(tx_1024byte_frames),
798da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(net_bytes),
799da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(rx_sof_overruns),
800da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(rx_mof_overruns),
801da866ba0SKaricheri, Muralidharan 	GBE_STATSB_INFO(rx_dma_overruns),
8026f8d3f33SWingman Kwok 	/* GBE module C */
803da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(rx_good_frames),
804da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(rx_broadcast_frames),
805da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(rx_multicast_frames),
806da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(rx_pause_frames),
807da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(rx_crc_errors),
808da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(rx_align_code_errors),
809da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(rx_oversized_frames),
810da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(rx_jabber_frames),
811da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(rx_undersized_frames),
812da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(rx_fragments),
813da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(rx_bytes),
814da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(tx_good_frames),
815da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(tx_broadcast_frames),
816da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(tx_multicast_frames),
817da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(tx_pause_frames),
818da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(tx_deferred_frames),
819da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(tx_collision_frames),
820da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(tx_single_coll_frames),
821da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(tx_mult_coll_frames),
822da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(tx_excessive_collisions),
823da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(tx_late_collisions),
824da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(tx_underrun),
825da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(tx_carrier_sense_errors),
826da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(tx_bytes),
827da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(tx_64byte_frames),
828da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(tx_65_to_127byte_frames),
829da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(tx_128_to_255byte_frames),
830da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(tx_256_to_511byte_frames),
831da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(tx_512_to_1023byte_frames),
832da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(tx_1024byte_frames),
833da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(net_bytes),
834da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(rx_sof_overruns),
835da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(rx_mof_overruns),
836da866ba0SKaricheri, Muralidharan 	GBE_STATSC_INFO(rx_dma_overruns),
8376f8d3f33SWingman Kwok 	/* GBE module D */
838da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(rx_good_frames),
839da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(rx_broadcast_frames),
840da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(rx_multicast_frames),
841da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(rx_pause_frames),
842da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(rx_crc_errors),
843da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(rx_align_code_errors),
844da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(rx_oversized_frames),
845da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(rx_jabber_frames),
846da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(rx_undersized_frames),
847da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(rx_fragments),
848da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(rx_bytes),
849da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(tx_good_frames),
850da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(tx_broadcast_frames),
851da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(tx_multicast_frames),
852da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(tx_pause_frames),
853da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(tx_deferred_frames),
854da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(tx_collision_frames),
855da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(tx_single_coll_frames),
856da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(tx_mult_coll_frames),
857da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(tx_excessive_collisions),
858da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(tx_late_collisions),
859da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(tx_underrun),
860da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(tx_carrier_sense_errors),
861da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(tx_bytes),
862da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(tx_64byte_frames),
863da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(tx_65_to_127byte_frames),
864da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(tx_128_to_255byte_frames),
865da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(tx_256_to_511byte_frames),
866da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(tx_512_to_1023byte_frames),
867da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(tx_1024byte_frames),
868da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(net_bytes),
869da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(rx_sof_overruns),
870da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(rx_mof_overruns),
871da866ba0SKaricheri, Muralidharan 	GBE_STATSD_INFO(rx_dma_overruns),
8726f8d3f33SWingman Kwok };
8736f8d3f33SWingman Kwok 
8749a391c7bSWingMan Kwok /* This is the size of entries in GBENU_STATS_HOST */
8755be4001eSWingMan Kwok #define GBENU_ET_STATS_HOST_SIZE	52
8769a391c7bSWingMan Kwok 
8779a391c7bSWingMan Kwok #define GBENU_STATS_HOST(field)					\
8789a391c7bSWingMan Kwok {								\
8799a391c7bSWingMan Kwok 	"GBE_HOST:"#field, GBENU_STATS0_MODULE,			\
8809a391c7bSWingMan Kwok 	FIELD_SIZEOF(struct gbenu_hw_stats, field),		\
8819a391c7bSWingMan Kwok 	offsetof(struct gbenu_hw_stats, field)			\
8829a391c7bSWingMan Kwok }
8839a391c7bSWingMan Kwok 
8845be4001eSWingMan Kwok /* This is the size of entries in GBENU_STATS_PORT */
8855be4001eSWingMan Kwok #define GBENU_ET_STATS_PORT_SIZE	65
8869a391c7bSWingMan Kwok 
8879a391c7bSWingMan Kwok #define GBENU_STATS_P1(field)					\
8889a391c7bSWingMan Kwok {								\
8899a391c7bSWingMan Kwok 	"GBE_P1:"#field, GBENU_STATS1_MODULE,			\
8909a391c7bSWingMan Kwok 	FIELD_SIZEOF(struct gbenu_hw_stats, field),		\
8919a391c7bSWingMan Kwok 	offsetof(struct gbenu_hw_stats, field)			\
8929a391c7bSWingMan Kwok }
8939a391c7bSWingMan Kwok 
8949a391c7bSWingMan Kwok #define GBENU_STATS_P2(field)					\
8959a391c7bSWingMan Kwok {								\
8969a391c7bSWingMan Kwok 	"GBE_P2:"#field, GBENU_STATS2_MODULE,			\
8979a391c7bSWingMan Kwok 	FIELD_SIZEOF(struct gbenu_hw_stats, field),		\
8989a391c7bSWingMan Kwok 	offsetof(struct gbenu_hw_stats, field)			\
8999a391c7bSWingMan Kwok }
9009a391c7bSWingMan Kwok 
9019a391c7bSWingMan Kwok #define GBENU_STATS_P3(field)					\
9029a391c7bSWingMan Kwok {								\
9039a391c7bSWingMan Kwok 	"GBE_P3:"#field, GBENU_STATS3_MODULE,			\
9049a391c7bSWingMan Kwok 	FIELD_SIZEOF(struct gbenu_hw_stats, field),		\
9059a391c7bSWingMan Kwok 	offsetof(struct gbenu_hw_stats, field)			\
9069a391c7bSWingMan Kwok }
9079a391c7bSWingMan Kwok 
9089a391c7bSWingMan Kwok #define GBENU_STATS_P4(field)					\
9099a391c7bSWingMan Kwok {								\
9109a391c7bSWingMan Kwok 	"GBE_P4:"#field, GBENU_STATS4_MODULE,			\
9119a391c7bSWingMan Kwok 	FIELD_SIZEOF(struct gbenu_hw_stats, field),		\
9129a391c7bSWingMan Kwok 	offsetof(struct gbenu_hw_stats, field)			\
9139a391c7bSWingMan Kwok }
9149a391c7bSWingMan Kwok 
9159a391c7bSWingMan Kwok #define GBENU_STATS_P5(field)					\
9169a391c7bSWingMan Kwok {								\
9179a391c7bSWingMan Kwok 	"GBE_P5:"#field, GBENU_STATS5_MODULE,			\
9189a391c7bSWingMan Kwok 	FIELD_SIZEOF(struct gbenu_hw_stats, field),		\
9199a391c7bSWingMan Kwok 	offsetof(struct gbenu_hw_stats, field)			\
9209a391c7bSWingMan Kwok }
9219a391c7bSWingMan Kwok 
9229a391c7bSWingMan Kwok #define GBENU_STATS_P6(field)					\
9239a391c7bSWingMan Kwok {								\
9249a391c7bSWingMan Kwok 	"GBE_P6:"#field, GBENU_STATS6_MODULE,			\
9259a391c7bSWingMan Kwok 	FIELD_SIZEOF(struct gbenu_hw_stats, field),		\
9269a391c7bSWingMan Kwok 	offsetof(struct gbenu_hw_stats, field)			\
9279a391c7bSWingMan Kwok }
9289a391c7bSWingMan Kwok 
9299a391c7bSWingMan Kwok #define GBENU_STATS_P7(field)					\
9309a391c7bSWingMan Kwok {								\
9319a391c7bSWingMan Kwok 	"GBE_P7:"#field, GBENU_STATS7_MODULE,			\
9329a391c7bSWingMan Kwok 	FIELD_SIZEOF(struct gbenu_hw_stats, field),		\
9339a391c7bSWingMan Kwok 	offsetof(struct gbenu_hw_stats, field)			\
9349a391c7bSWingMan Kwok }
9359a391c7bSWingMan Kwok 
9369a391c7bSWingMan Kwok #define GBENU_STATS_P8(field)					\
9379a391c7bSWingMan Kwok {								\
9389a391c7bSWingMan Kwok 	"GBE_P8:"#field, GBENU_STATS8_MODULE,			\
9399a391c7bSWingMan Kwok 	FIELD_SIZEOF(struct gbenu_hw_stats, field),		\
9409a391c7bSWingMan Kwok 	offsetof(struct gbenu_hw_stats, field)			\
9419a391c7bSWingMan Kwok }
9429a391c7bSWingMan Kwok 
9439a391c7bSWingMan Kwok static const struct netcp_ethtool_stat gbenu_et_stats[] = {
9449a391c7bSWingMan Kwok 	/* GBENU Host Module */
9459a391c7bSWingMan Kwok 	GBENU_STATS_HOST(rx_good_frames),
9469a391c7bSWingMan Kwok 	GBENU_STATS_HOST(rx_broadcast_frames),
9479a391c7bSWingMan Kwok 	GBENU_STATS_HOST(rx_multicast_frames),
9489a391c7bSWingMan Kwok 	GBENU_STATS_HOST(rx_crc_errors),
9499a391c7bSWingMan Kwok 	GBENU_STATS_HOST(rx_oversized_frames),
9509a391c7bSWingMan Kwok 	GBENU_STATS_HOST(rx_undersized_frames),
9519a391c7bSWingMan Kwok 	GBENU_STATS_HOST(ale_drop),
9529a391c7bSWingMan Kwok 	GBENU_STATS_HOST(ale_overrun_drop),
9539a391c7bSWingMan Kwok 	GBENU_STATS_HOST(rx_bytes),
9549a391c7bSWingMan Kwok 	GBENU_STATS_HOST(tx_good_frames),
9559a391c7bSWingMan Kwok 	GBENU_STATS_HOST(tx_broadcast_frames),
9569a391c7bSWingMan Kwok 	GBENU_STATS_HOST(tx_multicast_frames),
9579a391c7bSWingMan Kwok 	GBENU_STATS_HOST(tx_bytes),
9589a391c7bSWingMan Kwok 	GBENU_STATS_HOST(tx_64B_frames),
9599a391c7bSWingMan Kwok 	GBENU_STATS_HOST(tx_65_to_127B_frames),
9609a391c7bSWingMan Kwok 	GBENU_STATS_HOST(tx_128_to_255B_frames),
9619a391c7bSWingMan Kwok 	GBENU_STATS_HOST(tx_256_to_511B_frames),
9629a391c7bSWingMan Kwok 	GBENU_STATS_HOST(tx_512_to_1023B_frames),
9639a391c7bSWingMan Kwok 	GBENU_STATS_HOST(tx_1024B_frames),
9649a391c7bSWingMan Kwok 	GBENU_STATS_HOST(net_bytes),
9659a391c7bSWingMan Kwok 	GBENU_STATS_HOST(rx_bottom_fifo_drop),
9669a391c7bSWingMan Kwok 	GBENU_STATS_HOST(rx_port_mask_drop),
9679a391c7bSWingMan Kwok 	GBENU_STATS_HOST(rx_top_fifo_drop),
9689a391c7bSWingMan Kwok 	GBENU_STATS_HOST(ale_rate_limit_drop),
9699a391c7bSWingMan Kwok 	GBENU_STATS_HOST(ale_vid_ingress_drop),
9709a391c7bSWingMan Kwok 	GBENU_STATS_HOST(ale_da_eq_sa_drop),
9719a391c7bSWingMan Kwok 	GBENU_STATS_HOST(ale_unknown_ucast),
9729a391c7bSWingMan Kwok 	GBENU_STATS_HOST(ale_unknown_ucast_bytes),
9739a391c7bSWingMan Kwok 	GBENU_STATS_HOST(ale_unknown_mcast),
9749a391c7bSWingMan Kwok 	GBENU_STATS_HOST(ale_unknown_mcast_bytes),
9759a391c7bSWingMan Kwok 	GBENU_STATS_HOST(ale_unknown_bcast),
9769a391c7bSWingMan Kwok 	GBENU_STATS_HOST(ale_unknown_bcast_bytes),
9775be4001eSWingMan Kwok 	GBENU_STATS_HOST(ale_pol_match),
9785be4001eSWingMan Kwok 	GBENU_STATS_HOST(ale_pol_match_red),
9795be4001eSWingMan Kwok 	GBENU_STATS_HOST(ale_pol_match_yellow),
9809a391c7bSWingMan Kwok 	GBENU_STATS_HOST(tx_mem_protect_err),
9815be4001eSWingMan Kwok 	GBENU_STATS_HOST(tx_pri0_drop),
9825be4001eSWingMan Kwok 	GBENU_STATS_HOST(tx_pri1_drop),
9835be4001eSWingMan Kwok 	GBENU_STATS_HOST(tx_pri2_drop),
9845be4001eSWingMan Kwok 	GBENU_STATS_HOST(tx_pri3_drop),
9855be4001eSWingMan Kwok 	GBENU_STATS_HOST(tx_pri4_drop),
9865be4001eSWingMan Kwok 	GBENU_STATS_HOST(tx_pri5_drop),
9875be4001eSWingMan Kwok 	GBENU_STATS_HOST(tx_pri6_drop),
9885be4001eSWingMan Kwok 	GBENU_STATS_HOST(tx_pri7_drop),
9895be4001eSWingMan Kwok 	GBENU_STATS_HOST(tx_pri0_drop_bcnt),
9905be4001eSWingMan Kwok 	GBENU_STATS_HOST(tx_pri1_drop_bcnt),
9915be4001eSWingMan Kwok 	GBENU_STATS_HOST(tx_pri2_drop_bcnt),
9925be4001eSWingMan Kwok 	GBENU_STATS_HOST(tx_pri3_drop_bcnt),
9935be4001eSWingMan Kwok 	GBENU_STATS_HOST(tx_pri4_drop_bcnt),
9945be4001eSWingMan Kwok 	GBENU_STATS_HOST(tx_pri5_drop_bcnt),
9955be4001eSWingMan Kwok 	GBENU_STATS_HOST(tx_pri6_drop_bcnt),
9965be4001eSWingMan Kwok 	GBENU_STATS_HOST(tx_pri7_drop_bcnt),
9979a391c7bSWingMan Kwok 	/* GBENU Module 1 */
9989a391c7bSWingMan Kwok 	GBENU_STATS_P1(rx_good_frames),
9999a391c7bSWingMan Kwok 	GBENU_STATS_P1(rx_broadcast_frames),
10009a391c7bSWingMan Kwok 	GBENU_STATS_P1(rx_multicast_frames),
10019a391c7bSWingMan Kwok 	GBENU_STATS_P1(rx_pause_frames),
10029a391c7bSWingMan Kwok 	GBENU_STATS_P1(rx_crc_errors),
10039a391c7bSWingMan Kwok 	GBENU_STATS_P1(rx_align_code_errors),
10049a391c7bSWingMan Kwok 	GBENU_STATS_P1(rx_oversized_frames),
10059a391c7bSWingMan Kwok 	GBENU_STATS_P1(rx_jabber_frames),
10069a391c7bSWingMan Kwok 	GBENU_STATS_P1(rx_undersized_frames),
10079a391c7bSWingMan Kwok 	GBENU_STATS_P1(rx_fragments),
10089a391c7bSWingMan Kwok 	GBENU_STATS_P1(ale_drop),
10099a391c7bSWingMan Kwok 	GBENU_STATS_P1(ale_overrun_drop),
10109a391c7bSWingMan Kwok 	GBENU_STATS_P1(rx_bytes),
10119a391c7bSWingMan Kwok 	GBENU_STATS_P1(tx_good_frames),
10129a391c7bSWingMan Kwok 	GBENU_STATS_P1(tx_broadcast_frames),
10139a391c7bSWingMan Kwok 	GBENU_STATS_P1(tx_multicast_frames),
10149a391c7bSWingMan Kwok 	GBENU_STATS_P1(tx_pause_frames),
10159a391c7bSWingMan Kwok 	GBENU_STATS_P1(tx_deferred_frames),
10169a391c7bSWingMan Kwok 	GBENU_STATS_P1(tx_collision_frames),
10179a391c7bSWingMan Kwok 	GBENU_STATS_P1(tx_single_coll_frames),
10189a391c7bSWingMan Kwok 	GBENU_STATS_P1(tx_mult_coll_frames),
10199a391c7bSWingMan Kwok 	GBENU_STATS_P1(tx_excessive_collisions),
10209a391c7bSWingMan Kwok 	GBENU_STATS_P1(tx_late_collisions),
10219a391c7bSWingMan Kwok 	GBENU_STATS_P1(rx_ipg_error),
10229a391c7bSWingMan Kwok 	GBENU_STATS_P1(tx_carrier_sense_errors),
10239a391c7bSWingMan Kwok 	GBENU_STATS_P1(tx_bytes),
10249a391c7bSWingMan Kwok 	GBENU_STATS_P1(tx_64B_frames),
10259a391c7bSWingMan Kwok 	GBENU_STATS_P1(tx_65_to_127B_frames),
10269a391c7bSWingMan Kwok 	GBENU_STATS_P1(tx_128_to_255B_frames),
10279a391c7bSWingMan Kwok 	GBENU_STATS_P1(tx_256_to_511B_frames),
10289a391c7bSWingMan Kwok 	GBENU_STATS_P1(tx_512_to_1023B_frames),
10299a391c7bSWingMan Kwok 	GBENU_STATS_P1(tx_1024B_frames),
10309a391c7bSWingMan Kwok 	GBENU_STATS_P1(net_bytes),
10319a391c7bSWingMan Kwok 	GBENU_STATS_P1(rx_bottom_fifo_drop),
10329a391c7bSWingMan Kwok 	GBENU_STATS_P1(rx_port_mask_drop),
10339a391c7bSWingMan Kwok 	GBENU_STATS_P1(rx_top_fifo_drop),
10349a391c7bSWingMan Kwok 	GBENU_STATS_P1(ale_rate_limit_drop),
10359a391c7bSWingMan Kwok 	GBENU_STATS_P1(ale_vid_ingress_drop),
10369a391c7bSWingMan Kwok 	GBENU_STATS_P1(ale_da_eq_sa_drop),
10379a391c7bSWingMan Kwok 	GBENU_STATS_P1(ale_unknown_ucast),
10389a391c7bSWingMan Kwok 	GBENU_STATS_P1(ale_unknown_ucast_bytes),
10399a391c7bSWingMan Kwok 	GBENU_STATS_P1(ale_unknown_mcast),
10409a391c7bSWingMan Kwok 	GBENU_STATS_P1(ale_unknown_mcast_bytes),
10419a391c7bSWingMan Kwok 	GBENU_STATS_P1(ale_unknown_bcast),
10429a391c7bSWingMan Kwok 	GBENU_STATS_P1(ale_unknown_bcast_bytes),
10435be4001eSWingMan Kwok 	GBENU_STATS_P1(ale_pol_match),
10445be4001eSWingMan Kwok 	GBENU_STATS_P1(ale_pol_match_red),
10455be4001eSWingMan Kwok 	GBENU_STATS_P1(ale_pol_match_yellow),
10469a391c7bSWingMan Kwok 	GBENU_STATS_P1(tx_mem_protect_err),
10475be4001eSWingMan Kwok 	GBENU_STATS_P1(tx_pri0_drop),
10485be4001eSWingMan Kwok 	GBENU_STATS_P1(tx_pri1_drop),
10495be4001eSWingMan Kwok 	GBENU_STATS_P1(tx_pri2_drop),
10505be4001eSWingMan Kwok 	GBENU_STATS_P1(tx_pri3_drop),
10515be4001eSWingMan Kwok 	GBENU_STATS_P1(tx_pri4_drop),
10525be4001eSWingMan Kwok 	GBENU_STATS_P1(tx_pri5_drop),
10535be4001eSWingMan Kwok 	GBENU_STATS_P1(tx_pri6_drop),
10545be4001eSWingMan Kwok 	GBENU_STATS_P1(tx_pri7_drop),
10555be4001eSWingMan Kwok 	GBENU_STATS_P1(tx_pri0_drop_bcnt),
10565be4001eSWingMan Kwok 	GBENU_STATS_P1(tx_pri1_drop_bcnt),
10575be4001eSWingMan Kwok 	GBENU_STATS_P1(tx_pri2_drop_bcnt),
10585be4001eSWingMan Kwok 	GBENU_STATS_P1(tx_pri3_drop_bcnt),
10595be4001eSWingMan Kwok 	GBENU_STATS_P1(tx_pri4_drop_bcnt),
10605be4001eSWingMan Kwok 	GBENU_STATS_P1(tx_pri5_drop_bcnt),
10615be4001eSWingMan Kwok 	GBENU_STATS_P1(tx_pri6_drop_bcnt),
10625be4001eSWingMan Kwok 	GBENU_STATS_P1(tx_pri7_drop_bcnt),
10639a391c7bSWingMan Kwok 	/* GBENU Module 2 */
10649a391c7bSWingMan Kwok 	GBENU_STATS_P2(rx_good_frames),
10659a391c7bSWingMan Kwok 	GBENU_STATS_P2(rx_broadcast_frames),
10669a391c7bSWingMan Kwok 	GBENU_STATS_P2(rx_multicast_frames),
10679a391c7bSWingMan Kwok 	GBENU_STATS_P2(rx_pause_frames),
10689a391c7bSWingMan Kwok 	GBENU_STATS_P2(rx_crc_errors),
10699a391c7bSWingMan Kwok 	GBENU_STATS_P2(rx_align_code_errors),
10709a391c7bSWingMan Kwok 	GBENU_STATS_P2(rx_oversized_frames),
10719a391c7bSWingMan Kwok 	GBENU_STATS_P2(rx_jabber_frames),
10729a391c7bSWingMan Kwok 	GBENU_STATS_P2(rx_undersized_frames),
10739a391c7bSWingMan Kwok 	GBENU_STATS_P2(rx_fragments),
10749a391c7bSWingMan Kwok 	GBENU_STATS_P2(ale_drop),
10759a391c7bSWingMan Kwok 	GBENU_STATS_P2(ale_overrun_drop),
10769a391c7bSWingMan Kwok 	GBENU_STATS_P2(rx_bytes),
10779a391c7bSWingMan Kwok 	GBENU_STATS_P2(tx_good_frames),
10789a391c7bSWingMan Kwok 	GBENU_STATS_P2(tx_broadcast_frames),
10799a391c7bSWingMan Kwok 	GBENU_STATS_P2(tx_multicast_frames),
10809a391c7bSWingMan Kwok 	GBENU_STATS_P2(tx_pause_frames),
10819a391c7bSWingMan Kwok 	GBENU_STATS_P2(tx_deferred_frames),
10829a391c7bSWingMan Kwok 	GBENU_STATS_P2(tx_collision_frames),
10839a391c7bSWingMan Kwok 	GBENU_STATS_P2(tx_single_coll_frames),
10849a391c7bSWingMan Kwok 	GBENU_STATS_P2(tx_mult_coll_frames),
10859a391c7bSWingMan Kwok 	GBENU_STATS_P2(tx_excessive_collisions),
10869a391c7bSWingMan Kwok 	GBENU_STATS_P2(tx_late_collisions),
10879a391c7bSWingMan Kwok 	GBENU_STATS_P2(rx_ipg_error),
10889a391c7bSWingMan Kwok 	GBENU_STATS_P2(tx_carrier_sense_errors),
10899a391c7bSWingMan Kwok 	GBENU_STATS_P2(tx_bytes),
10909a391c7bSWingMan Kwok 	GBENU_STATS_P2(tx_64B_frames),
10919a391c7bSWingMan Kwok 	GBENU_STATS_P2(tx_65_to_127B_frames),
10929a391c7bSWingMan Kwok 	GBENU_STATS_P2(tx_128_to_255B_frames),
10939a391c7bSWingMan Kwok 	GBENU_STATS_P2(tx_256_to_511B_frames),
10949a391c7bSWingMan Kwok 	GBENU_STATS_P2(tx_512_to_1023B_frames),
10959a391c7bSWingMan Kwok 	GBENU_STATS_P2(tx_1024B_frames),
10969a391c7bSWingMan Kwok 	GBENU_STATS_P2(net_bytes),
10979a391c7bSWingMan Kwok 	GBENU_STATS_P2(rx_bottom_fifo_drop),
10989a391c7bSWingMan Kwok 	GBENU_STATS_P2(rx_port_mask_drop),
10999a391c7bSWingMan Kwok 	GBENU_STATS_P2(rx_top_fifo_drop),
11009a391c7bSWingMan Kwok 	GBENU_STATS_P2(ale_rate_limit_drop),
11019a391c7bSWingMan Kwok 	GBENU_STATS_P2(ale_vid_ingress_drop),
11029a391c7bSWingMan Kwok 	GBENU_STATS_P2(ale_da_eq_sa_drop),
11039a391c7bSWingMan Kwok 	GBENU_STATS_P2(ale_unknown_ucast),
11049a391c7bSWingMan Kwok 	GBENU_STATS_P2(ale_unknown_ucast_bytes),
11059a391c7bSWingMan Kwok 	GBENU_STATS_P2(ale_unknown_mcast),
11069a391c7bSWingMan Kwok 	GBENU_STATS_P2(ale_unknown_mcast_bytes),
11079a391c7bSWingMan Kwok 	GBENU_STATS_P2(ale_unknown_bcast),
11089a391c7bSWingMan Kwok 	GBENU_STATS_P2(ale_unknown_bcast_bytes),
11095be4001eSWingMan Kwok 	GBENU_STATS_P2(ale_pol_match),
11105be4001eSWingMan Kwok 	GBENU_STATS_P2(ale_pol_match_red),
11115be4001eSWingMan Kwok 	GBENU_STATS_P2(ale_pol_match_yellow),
11129a391c7bSWingMan Kwok 	GBENU_STATS_P2(tx_mem_protect_err),
11135be4001eSWingMan Kwok 	GBENU_STATS_P2(tx_pri0_drop),
11145be4001eSWingMan Kwok 	GBENU_STATS_P2(tx_pri1_drop),
11155be4001eSWingMan Kwok 	GBENU_STATS_P2(tx_pri2_drop),
11165be4001eSWingMan Kwok 	GBENU_STATS_P2(tx_pri3_drop),
11175be4001eSWingMan Kwok 	GBENU_STATS_P2(tx_pri4_drop),
11185be4001eSWingMan Kwok 	GBENU_STATS_P2(tx_pri5_drop),
11195be4001eSWingMan Kwok 	GBENU_STATS_P2(tx_pri6_drop),
11205be4001eSWingMan Kwok 	GBENU_STATS_P2(tx_pri7_drop),
11215be4001eSWingMan Kwok 	GBENU_STATS_P2(tx_pri0_drop_bcnt),
11225be4001eSWingMan Kwok 	GBENU_STATS_P2(tx_pri1_drop_bcnt),
11235be4001eSWingMan Kwok 	GBENU_STATS_P2(tx_pri2_drop_bcnt),
11245be4001eSWingMan Kwok 	GBENU_STATS_P2(tx_pri3_drop_bcnt),
11255be4001eSWingMan Kwok 	GBENU_STATS_P2(tx_pri4_drop_bcnt),
11265be4001eSWingMan Kwok 	GBENU_STATS_P2(tx_pri5_drop_bcnt),
11275be4001eSWingMan Kwok 	GBENU_STATS_P2(tx_pri6_drop_bcnt),
11285be4001eSWingMan Kwok 	GBENU_STATS_P2(tx_pri7_drop_bcnt),
11299a391c7bSWingMan Kwok 	/* GBENU Module 3 */
11309a391c7bSWingMan Kwok 	GBENU_STATS_P3(rx_good_frames),
11319a391c7bSWingMan Kwok 	GBENU_STATS_P3(rx_broadcast_frames),
11329a391c7bSWingMan Kwok 	GBENU_STATS_P3(rx_multicast_frames),
11339a391c7bSWingMan Kwok 	GBENU_STATS_P3(rx_pause_frames),
11349a391c7bSWingMan Kwok 	GBENU_STATS_P3(rx_crc_errors),
11359a391c7bSWingMan Kwok 	GBENU_STATS_P3(rx_align_code_errors),
11369a391c7bSWingMan Kwok 	GBENU_STATS_P3(rx_oversized_frames),
11379a391c7bSWingMan Kwok 	GBENU_STATS_P3(rx_jabber_frames),
11389a391c7bSWingMan Kwok 	GBENU_STATS_P3(rx_undersized_frames),
11399a391c7bSWingMan Kwok 	GBENU_STATS_P3(rx_fragments),
11409a391c7bSWingMan Kwok 	GBENU_STATS_P3(ale_drop),
11419a391c7bSWingMan Kwok 	GBENU_STATS_P3(ale_overrun_drop),
11429a391c7bSWingMan Kwok 	GBENU_STATS_P3(rx_bytes),
11439a391c7bSWingMan Kwok 	GBENU_STATS_P3(tx_good_frames),
11449a391c7bSWingMan Kwok 	GBENU_STATS_P3(tx_broadcast_frames),
11459a391c7bSWingMan Kwok 	GBENU_STATS_P3(tx_multicast_frames),
11469a391c7bSWingMan Kwok 	GBENU_STATS_P3(tx_pause_frames),
11479a391c7bSWingMan Kwok 	GBENU_STATS_P3(tx_deferred_frames),
11489a391c7bSWingMan Kwok 	GBENU_STATS_P3(tx_collision_frames),
11499a391c7bSWingMan Kwok 	GBENU_STATS_P3(tx_single_coll_frames),
11509a391c7bSWingMan Kwok 	GBENU_STATS_P3(tx_mult_coll_frames),
11519a391c7bSWingMan Kwok 	GBENU_STATS_P3(tx_excessive_collisions),
11529a391c7bSWingMan Kwok 	GBENU_STATS_P3(tx_late_collisions),
11539a391c7bSWingMan Kwok 	GBENU_STATS_P3(rx_ipg_error),
11549a391c7bSWingMan Kwok 	GBENU_STATS_P3(tx_carrier_sense_errors),
11559a391c7bSWingMan Kwok 	GBENU_STATS_P3(tx_bytes),
11569a391c7bSWingMan Kwok 	GBENU_STATS_P3(tx_64B_frames),
11579a391c7bSWingMan Kwok 	GBENU_STATS_P3(tx_65_to_127B_frames),
11589a391c7bSWingMan Kwok 	GBENU_STATS_P3(tx_128_to_255B_frames),
11599a391c7bSWingMan Kwok 	GBENU_STATS_P3(tx_256_to_511B_frames),
11609a391c7bSWingMan Kwok 	GBENU_STATS_P3(tx_512_to_1023B_frames),
11619a391c7bSWingMan Kwok 	GBENU_STATS_P3(tx_1024B_frames),
11629a391c7bSWingMan Kwok 	GBENU_STATS_P3(net_bytes),
11639a391c7bSWingMan Kwok 	GBENU_STATS_P3(rx_bottom_fifo_drop),
11649a391c7bSWingMan Kwok 	GBENU_STATS_P3(rx_port_mask_drop),
11659a391c7bSWingMan Kwok 	GBENU_STATS_P3(rx_top_fifo_drop),
11669a391c7bSWingMan Kwok 	GBENU_STATS_P3(ale_rate_limit_drop),
11679a391c7bSWingMan Kwok 	GBENU_STATS_P3(ale_vid_ingress_drop),
11689a391c7bSWingMan Kwok 	GBENU_STATS_P3(ale_da_eq_sa_drop),
11699a391c7bSWingMan Kwok 	GBENU_STATS_P3(ale_unknown_ucast),
11709a391c7bSWingMan Kwok 	GBENU_STATS_P3(ale_unknown_ucast_bytes),
11719a391c7bSWingMan Kwok 	GBENU_STATS_P3(ale_unknown_mcast),
11729a391c7bSWingMan Kwok 	GBENU_STATS_P3(ale_unknown_mcast_bytes),
11739a391c7bSWingMan Kwok 	GBENU_STATS_P3(ale_unknown_bcast),
11749a391c7bSWingMan Kwok 	GBENU_STATS_P3(ale_unknown_bcast_bytes),
11755be4001eSWingMan Kwok 	GBENU_STATS_P3(ale_pol_match),
11765be4001eSWingMan Kwok 	GBENU_STATS_P3(ale_pol_match_red),
11775be4001eSWingMan Kwok 	GBENU_STATS_P3(ale_pol_match_yellow),
11789a391c7bSWingMan Kwok 	GBENU_STATS_P3(tx_mem_protect_err),
11795be4001eSWingMan Kwok 	GBENU_STATS_P3(tx_pri0_drop),
11805be4001eSWingMan Kwok 	GBENU_STATS_P3(tx_pri1_drop),
11815be4001eSWingMan Kwok 	GBENU_STATS_P3(tx_pri2_drop),
11825be4001eSWingMan Kwok 	GBENU_STATS_P3(tx_pri3_drop),
11835be4001eSWingMan Kwok 	GBENU_STATS_P3(tx_pri4_drop),
11845be4001eSWingMan Kwok 	GBENU_STATS_P3(tx_pri5_drop),
11855be4001eSWingMan Kwok 	GBENU_STATS_P3(tx_pri6_drop),
11865be4001eSWingMan Kwok 	GBENU_STATS_P3(tx_pri7_drop),
11875be4001eSWingMan Kwok 	GBENU_STATS_P3(tx_pri0_drop_bcnt),
11885be4001eSWingMan Kwok 	GBENU_STATS_P3(tx_pri1_drop_bcnt),
11895be4001eSWingMan Kwok 	GBENU_STATS_P3(tx_pri2_drop_bcnt),
11905be4001eSWingMan Kwok 	GBENU_STATS_P3(tx_pri3_drop_bcnt),
11915be4001eSWingMan Kwok 	GBENU_STATS_P3(tx_pri4_drop_bcnt),
11925be4001eSWingMan Kwok 	GBENU_STATS_P3(tx_pri5_drop_bcnt),
11935be4001eSWingMan Kwok 	GBENU_STATS_P3(tx_pri6_drop_bcnt),
11945be4001eSWingMan Kwok 	GBENU_STATS_P3(tx_pri7_drop_bcnt),
11959a391c7bSWingMan Kwok 	/* GBENU Module 4 */
11969a391c7bSWingMan Kwok 	GBENU_STATS_P4(rx_good_frames),
11979a391c7bSWingMan Kwok 	GBENU_STATS_P4(rx_broadcast_frames),
11989a391c7bSWingMan Kwok 	GBENU_STATS_P4(rx_multicast_frames),
11999a391c7bSWingMan Kwok 	GBENU_STATS_P4(rx_pause_frames),
12009a391c7bSWingMan Kwok 	GBENU_STATS_P4(rx_crc_errors),
12019a391c7bSWingMan Kwok 	GBENU_STATS_P4(rx_align_code_errors),
12029a391c7bSWingMan Kwok 	GBENU_STATS_P4(rx_oversized_frames),
12039a391c7bSWingMan Kwok 	GBENU_STATS_P4(rx_jabber_frames),
12049a391c7bSWingMan Kwok 	GBENU_STATS_P4(rx_undersized_frames),
12059a391c7bSWingMan Kwok 	GBENU_STATS_P4(rx_fragments),
12069a391c7bSWingMan Kwok 	GBENU_STATS_P4(ale_drop),
12079a391c7bSWingMan Kwok 	GBENU_STATS_P4(ale_overrun_drop),
12089a391c7bSWingMan Kwok 	GBENU_STATS_P4(rx_bytes),
12099a391c7bSWingMan Kwok 	GBENU_STATS_P4(tx_good_frames),
12109a391c7bSWingMan Kwok 	GBENU_STATS_P4(tx_broadcast_frames),
12119a391c7bSWingMan Kwok 	GBENU_STATS_P4(tx_multicast_frames),
12129a391c7bSWingMan Kwok 	GBENU_STATS_P4(tx_pause_frames),
12139a391c7bSWingMan Kwok 	GBENU_STATS_P4(tx_deferred_frames),
12149a391c7bSWingMan Kwok 	GBENU_STATS_P4(tx_collision_frames),
12159a391c7bSWingMan Kwok 	GBENU_STATS_P4(tx_single_coll_frames),
12169a391c7bSWingMan Kwok 	GBENU_STATS_P4(tx_mult_coll_frames),
12179a391c7bSWingMan Kwok 	GBENU_STATS_P4(tx_excessive_collisions),
12189a391c7bSWingMan Kwok 	GBENU_STATS_P4(tx_late_collisions),
12199a391c7bSWingMan Kwok 	GBENU_STATS_P4(rx_ipg_error),
12209a391c7bSWingMan Kwok 	GBENU_STATS_P4(tx_carrier_sense_errors),
12219a391c7bSWingMan Kwok 	GBENU_STATS_P4(tx_bytes),
12229a391c7bSWingMan Kwok 	GBENU_STATS_P4(tx_64B_frames),
12239a391c7bSWingMan Kwok 	GBENU_STATS_P4(tx_65_to_127B_frames),
12249a391c7bSWingMan Kwok 	GBENU_STATS_P4(tx_128_to_255B_frames),
12259a391c7bSWingMan Kwok 	GBENU_STATS_P4(tx_256_to_511B_frames),
12269a391c7bSWingMan Kwok 	GBENU_STATS_P4(tx_512_to_1023B_frames),
12279a391c7bSWingMan Kwok 	GBENU_STATS_P4(tx_1024B_frames),
12289a391c7bSWingMan Kwok 	GBENU_STATS_P4(net_bytes),
12299a391c7bSWingMan Kwok 	GBENU_STATS_P4(rx_bottom_fifo_drop),
12309a391c7bSWingMan Kwok 	GBENU_STATS_P4(rx_port_mask_drop),
12319a391c7bSWingMan Kwok 	GBENU_STATS_P4(rx_top_fifo_drop),
12329a391c7bSWingMan Kwok 	GBENU_STATS_P4(ale_rate_limit_drop),
12339a391c7bSWingMan Kwok 	GBENU_STATS_P4(ale_vid_ingress_drop),
12349a391c7bSWingMan Kwok 	GBENU_STATS_P4(ale_da_eq_sa_drop),
12359a391c7bSWingMan Kwok 	GBENU_STATS_P4(ale_unknown_ucast),
12369a391c7bSWingMan Kwok 	GBENU_STATS_P4(ale_unknown_ucast_bytes),
12379a391c7bSWingMan Kwok 	GBENU_STATS_P4(ale_unknown_mcast),
12389a391c7bSWingMan Kwok 	GBENU_STATS_P4(ale_unknown_mcast_bytes),
12399a391c7bSWingMan Kwok 	GBENU_STATS_P4(ale_unknown_bcast),
12409a391c7bSWingMan Kwok 	GBENU_STATS_P4(ale_unknown_bcast_bytes),
12415be4001eSWingMan Kwok 	GBENU_STATS_P4(ale_pol_match),
12425be4001eSWingMan Kwok 	GBENU_STATS_P4(ale_pol_match_red),
12435be4001eSWingMan Kwok 	GBENU_STATS_P4(ale_pol_match_yellow),
12449a391c7bSWingMan Kwok 	GBENU_STATS_P4(tx_mem_protect_err),
12455be4001eSWingMan Kwok 	GBENU_STATS_P4(tx_pri0_drop),
12465be4001eSWingMan Kwok 	GBENU_STATS_P4(tx_pri1_drop),
12475be4001eSWingMan Kwok 	GBENU_STATS_P4(tx_pri2_drop),
12485be4001eSWingMan Kwok 	GBENU_STATS_P4(tx_pri3_drop),
12495be4001eSWingMan Kwok 	GBENU_STATS_P4(tx_pri4_drop),
12505be4001eSWingMan Kwok 	GBENU_STATS_P4(tx_pri5_drop),
12515be4001eSWingMan Kwok 	GBENU_STATS_P4(tx_pri6_drop),
12525be4001eSWingMan Kwok 	GBENU_STATS_P4(tx_pri7_drop),
12535be4001eSWingMan Kwok 	GBENU_STATS_P4(tx_pri0_drop_bcnt),
12545be4001eSWingMan Kwok 	GBENU_STATS_P4(tx_pri1_drop_bcnt),
12555be4001eSWingMan Kwok 	GBENU_STATS_P4(tx_pri2_drop_bcnt),
12565be4001eSWingMan Kwok 	GBENU_STATS_P4(tx_pri3_drop_bcnt),
12575be4001eSWingMan Kwok 	GBENU_STATS_P4(tx_pri4_drop_bcnt),
12585be4001eSWingMan Kwok 	GBENU_STATS_P4(tx_pri5_drop_bcnt),
12595be4001eSWingMan Kwok 	GBENU_STATS_P4(tx_pri6_drop_bcnt),
12605be4001eSWingMan Kwok 	GBENU_STATS_P4(tx_pri7_drop_bcnt),
12619a391c7bSWingMan Kwok 	/* GBENU Module 5 */
12629a391c7bSWingMan Kwok 	GBENU_STATS_P5(rx_good_frames),
12639a391c7bSWingMan Kwok 	GBENU_STATS_P5(rx_broadcast_frames),
12649a391c7bSWingMan Kwok 	GBENU_STATS_P5(rx_multicast_frames),
12659a391c7bSWingMan Kwok 	GBENU_STATS_P5(rx_pause_frames),
12669a391c7bSWingMan Kwok 	GBENU_STATS_P5(rx_crc_errors),
12679a391c7bSWingMan Kwok 	GBENU_STATS_P5(rx_align_code_errors),
12689a391c7bSWingMan Kwok 	GBENU_STATS_P5(rx_oversized_frames),
12699a391c7bSWingMan Kwok 	GBENU_STATS_P5(rx_jabber_frames),
12709a391c7bSWingMan Kwok 	GBENU_STATS_P5(rx_undersized_frames),
12719a391c7bSWingMan Kwok 	GBENU_STATS_P5(rx_fragments),
12729a391c7bSWingMan Kwok 	GBENU_STATS_P5(ale_drop),
12739a391c7bSWingMan Kwok 	GBENU_STATS_P5(ale_overrun_drop),
12749a391c7bSWingMan Kwok 	GBENU_STATS_P5(rx_bytes),
12759a391c7bSWingMan Kwok 	GBENU_STATS_P5(tx_good_frames),
12769a391c7bSWingMan Kwok 	GBENU_STATS_P5(tx_broadcast_frames),
12779a391c7bSWingMan Kwok 	GBENU_STATS_P5(tx_multicast_frames),
12789a391c7bSWingMan Kwok 	GBENU_STATS_P5(tx_pause_frames),
12799a391c7bSWingMan Kwok 	GBENU_STATS_P5(tx_deferred_frames),
12809a391c7bSWingMan Kwok 	GBENU_STATS_P5(tx_collision_frames),
12819a391c7bSWingMan Kwok 	GBENU_STATS_P5(tx_single_coll_frames),
12829a391c7bSWingMan Kwok 	GBENU_STATS_P5(tx_mult_coll_frames),
12839a391c7bSWingMan Kwok 	GBENU_STATS_P5(tx_excessive_collisions),
12849a391c7bSWingMan Kwok 	GBENU_STATS_P5(tx_late_collisions),
12859a391c7bSWingMan Kwok 	GBENU_STATS_P5(rx_ipg_error),
12869a391c7bSWingMan Kwok 	GBENU_STATS_P5(tx_carrier_sense_errors),
12879a391c7bSWingMan Kwok 	GBENU_STATS_P5(tx_bytes),
12889a391c7bSWingMan Kwok 	GBENU_STATS_P5(tx_64B_frames),
12899a391c7bSWingMan Kwok 	GBENU_STATS_P5(tx_65_to_127B_frames),
12909a391c7bSWingMan Kwok 	GBENU_STATS_P5(tx_128_to_255B_frames),
12919a391c7bSWingMan Kwok 	GBENU_STATS_P5(tx_256_to_511B_frames),
12929a391c7bSWingMan Kwok 	GBENU_STATS_P5(tx_512_to_1023B_frames),
12939a391c7bSWingMan Kwok 	GBENU_STATS_P5(tx_1024B_frames),
12949a391c7bSWingMan Kwok 	GBENU_STATS_P5(net_bytes),
12959a391c7bSWingMan Kwok 	GBENU_STATS_P5(rx_bottom_fifo_drop),
12969a391c7bSWingMan Kwok 	GBENU_STATS_P5(rx_port_mask_drop),
12979a391c7bSWingMan Kwok 	GBENU_STATS_P5(rx_top_fifo_drop),
12989a391c7bSWingMan Kwok 	GBENU_STATS_P5(ale_rate_limit_drop),
12999a391c7bSWingMan Kwok 	GBENU_STATS_P5(ale_vid_ingress_drop),
13009a391c7bSWingMan Kwok 	GBENU_STATS_P5(ale_da_eq_sa_drop),
13019a391c7bSWingMan Kwok 	GBENU_STATS_P5(ale_unknown_ucast),
13029a391c7bSWingMan Kwok 	GBENU_STATS_P5(ale_unknown_ucast_bytes),
13039a391c7bSWingMan Kwok 	GBENU_STATS_P5(ale_unknown_mcast),
13049a391c7bSWingMan Kwok 	GBENU_STATS_P5(ale_unknown_mcast_bytes),
13059a391c7bSWingMan Kwok 	GBENU_STATS_P5(ale_unknown_bcast),
13069a391c7bSWingMan Kwok 	GBENU_STATS_P5(ale_unknown_bcast_bytes),
13075be4001eSWingMan Kwok 	GBENU_STATS_P5(ale_pol_match),
13085be4001eSWingMan Kwok 	GBENU_STATS_P5(ale_pol_match_red),
13095be4001eSWingMan Kwok 	GBENU_STATS_P5(ale_pol_match_yellow),
13109a391c7bSWingMan Kwok 	GBENU_STATS_P5(tx_mem_protect_err),
13115be4001eSWingMan Kwok 	GBENU_STATS_P5(tx_pri0_drop),
13125be4001eSWingMan Kwok 	GBENU_STATS_P5(tx_pri1_drop),
13135be4001eSWingMan Kwok 	GBENU_STATS_P5(tx_pri2_drop),
13145be4001eSWingMan Kwok 	GBENU_STATS_P5(tx_pri3_drop),
13155be4001eSWingMan Kwok 	GBENU_STATS_P5(tx_pri4_drop),
13165be4001eSWingMan Kwok 	GBENU_STATS_P5(tx_pri5_drop),
13175be4001eSWingMan Kwok 	GBENU_STATS_P5(tx_pri6_drop),
13185be4001eSWingMan Kwok 	GBENU_STATS_P5(tx_pri7_drop),
13195be4001eSWingMan Kwok 	GBENU_STATS_P5(tx_pri0_drop_bcnt),
13205be4001eSWingMan Kwok 	GBENU_STATS_P5(tx_pri1_drop_bcnt),
13215be4001eSWingMan Kwok 	GBENU_STATS_P5(tx_pri2_drop_bcnt),
13225be4001eSWingMan Kwok 	GBENU_STATS_P5(tx_pri3_drop_bcnt),
13235be4001eSWingMan Kwok 	GBENU_STATS_P5(tx_pri4_drop_bcnt),
13245be4001eSWingMan Kwok 	GBENU_STATS_P5(tx_pri5_drop_bcnt),
13255be4001eSWingMan Kwok 	GBENU_STATS_P5(tx_pri6_drop_bcnt),
13265be4001eSWingMan Kwok 	GBENU_STATS_P5(tx_pri7_drop_bcnt),
13279a391c7bSWingMan Kwok 	/* GBENU Module 6 */
13289a391c7bSWingMan Kwok 	GBENU_STATS_P6(rx_good_frames),
13299a391c7bSWingMan Kwok 	GBENU_STATS_P6(rx_broadcast_frames),
13309a391c7bSWingMan Kwok 	GBENU_STATS_P6(rx_multicast_frames),
13319a391c7bSWingMan Kwok 	GBENU_STATS_P6(rx_pause_frames),
13329a391c7bSWingMan Kwok 	GBENU_STATS_P6(rx_crc_errors),
13339a391c7bSWingMan Kwok 	GBENU_STATS_P6(rx_align_code_errors),
13349a391c7bSWingMan Kwok 	GBENU_STATS_P6(rx_oversized_frames),
13359a391c7bSWingMan Kwok 	GBENU_STATS_P6(rx_jabber_frames),
13369a391c7bSWingMan Kwok 	GBENU_STATS_P6(rx_undersized_frames),
13379a391c7bSWingMan Kwok 	GBENU_STATS_P6(rx_fragments),
13389a391c7bSWingMan Kwok 	GBENU_STATS_P6(ale_drop),
13399a391c7bSWingMan Kwok 	GBENU_STATS_P6(ale_overrun_drop),
13409a391c7bSWingMan Kwok 	GBENU_STATS_P6(rx_bytes),
13419a391c7bSWingMan Kwok 	GBENU_STATS_P6(tx_good_frames),
13429a391c7bSWingMan Kwok 	GBENU_STATS_P6(tx_broadcast_frames),
13439a391c7bSWingMan Kwok 	GBENU_STATS_P6(tx_multicast_frames),
13449a391c7bSWingMan Kwok 	GBENU_STATS_P6(tx_pause_frames),
13459a391c7bSWingMan Kwok 	GBENU_STATS_P6(tx_deferred_frames),
13469a391c7bSWingMan Kwok 	GBENU_STATS_P6(tx_collision_frames),
13479a391c7bSWingMan Kwok 	GBENU_STATS_P6(tx_single_coll_frames),
13489a391c7bSWingMan Kwok 	GBENU_STATS_P6(tx_mult_coll_frames),
13499a391c7bSWingMan Kwok 	GBENU_STATS_P6(tx_excessive_collisions),
13509a391c7bSWingMan Kwok 	GBENU_STATS_P6(tx_late_collisions),
13519a391c7bSWingMan Kwok 	GBENU_STATS_P6(rx_ipg_error),
13529a391c7bSWingMan Kwok 	GBENU_STATS_P6(tx_carrier_sense_errors),
13539a391c7bSWingMan Kwok 	GBENU_STATS_P6(tx_bytes),
13549a391c7bSWingMan Kwok 	GBENU_STATS_P6(tx_64B_frames),
13559a391c7bSWingMan Kwok 	GBENU_STATS_P6(tx_65_to_127B_frames),
13569a391c7bSWingMan Kwok 	GBENU_STATS_P6(tx_128_to_255B_frames),
13579a391c7bSWingMan Kwok 	GBENU_STATS_P6(tx_256_to_511B_frames),
13589a391c7bSWingMan Kwok 	GBENU_STATS_P6(tx_512_to_1023B_frames),
13599a391c7bSWingMan Kwok 	GBENU_STATS_P6(tx_1024B_frames),
13609a391c7bSWingMan Kwok 	GBENU_STATS_P6(net_bytes),
13619a391c7bSWingMan Kwok 	GBENU_STATS_P6(rx_bottom_fifo_drop),
13629a391c7bSWingMan Kwok 	GBENU_STATS_P6(rx_port_mask_drop),
13639a391c7bSWingMan Kwok 	GBENU_STATS_P6(rx_top_fifo_drop),
13649a391c7bSWingMan Kwok 	GBENU_STATS_P6(ale_rate_limit_drop),
13659a391c7bSWingMan Kwok 	GBENU_STATS_P6(ale_vid_ingress_drop),
13669a391c7bSWingMan Kwok 	GBENU_STATS_P6(ale_da_eq_sa_drop),
13679a391c7bSWingMan Kwok 	GBENU_STATS_P6(ale_unknown_ucast),
13689a391c7bSWingMan Kwok 	GBENU_STATS_P6(ale_unknown_ucast_bytes),
13699a391c7bSWingMan Kwok 	GBENU_STATS_P6(ale_unknown_mcast),
13709a391c7bSWingMan Kwok 	GBENU_STATS_P6(ale_unknown_mcast_bytes),
13719a391c7bSWingMan Kwok 	GBENU_STATS_P6(ale_unknown_bcast),
13729a391c7bSWingMan Kwok 	GBENU_STATS_P6(ale_unknown_bcast_bytes),
13735be4001eSWingMan Kwok 	GBENU_STATS_P6(ale_pol_match),
13745be4001eSWingMan Kwok 	GBENU_STATS_P6(ale_pol_match_red),
13755be4001eSWingMan Kwok 	GBENU_STATS_P6(ale_pol_match_yellow),
13769a391c7bSWingMan Kwok 	GBENU_STATS_P6(tx_mem_protect_err),
13775be4001eSWingMan Kwok 	GBENU_STATS_P6(tx_pri0_drop),
13785be4001eSWingMan Kwok 	GBENU_STATS_P6(tx_pri1_drop),
13795be4001eSWingMan Kwok 	GBENU_STATS_P6(tx_pri2_drop),
13805be4001eSWingMan Kwok 	GBENU_STATS_P6(tx_pri3_drop),
13815be4001eSWingMan Kwok 	GBENU_STATS_P6(tx_pri4_drop),
13825be4001eSWingMan Kwok 	GBENU_STATS_P6(tx_pri5_drop),
13835be4001eSWingMan Kwok 	GBENU_STATS_P6(tx_pri6_drop),
13845be4001eSWingMan Kwok 	GBENU_STATS_P6(tx_pri7_drop),
13855be4001eSWingMan Kwok 	GBENU_STATS_P6(tx_pri0_drop_bcnt),
13865be4001eSWingMan Kwok 	GBENU_STATS_P6(tx_pri1_drop_bcnt),
13875be4001eSWingMan Kwok 	GBENU_STATS_P6(tx_pri2_drop_bcnt),
13885be4001eSWingMan Kwok 	GBENU_STATS_P6(tx_pri3_drop_bcnt),
13895be4001eSWingMan Kwok 	GBENU_STATS_P6(tx_pri4_drop_bcnt),
13905be4001eSWingMan Kwok 	GBENU_STATS_P6(tx_pri5_drop_bcnt),
13915be4001eSWingMan Kwok 	GBENU_STATS_P6(tx_pri6_drop_bcnt),
13925be4001eSWingMan Kwok 	GBENU_STATS_P6(tx_pri7_drop_bcnt),
13939a391c7bSWingMan Kwok 	/* GBENU Module 7 */
13949a391c7bSWingMan Kwok 	GBENU_STATS_P7(rx_good_frames),
13959a391c7bSWingMan Kwok 	GBENU_STATS_P7(rx_broadcast_frames),
13969a391c7bSWingMan Kwok 	GBENU_STATS_P7(rx_multicast_frames),
13979a391c7bSWingMan Kwok 	GBENU_STATS_P7(rx_pause_frames),
13989a391c7bSWingMan Kwok 	GBENU_STATS_P7(rx_crc_errors),
13999a391c7bSWingMan Kwok 	GBENU_STATS_P7(rx_align_code_errors),
14009a391c7bSWingMan Kwok 	GBENU_STATS_P7(rx_oversized_frames),
14019a391c7bSWingMan Kwok 	GBENU_STATS_P7(rx_jabber_frames),
14029a391c7bSWingMan Kwok 	GBENU_STATS_P7(rx_undersized_frames),
14039a391c7bSWingMan Kwok 	GBENU_STATS_P7(rx_fragments),
14049a391c7bSWingMan Kwok 	GBENU_STATS_P7(ale_drop),
14059a391c7bSWingMan Kwok 	GBENU_STATS_P7(ale_overrun_drop),
14069a391c7bSWingMan Kwok 	GBENU_STATS_P7(rx_bytes),
14079a391c7bSWingMan Kwok 	GBENU_STATS_P7(tx_good_frames),
14089a391c7bSWingMan Kwok 	GBENU_STATS_P7(tx_broadcast_frames),
14099a391c7bSWingMan Kwok 	GBENU_STATS_P7(tx_multicast_frames),
14109a391c7bSWingMan Kwok 	GBENU_STATS_P7(tx_pause_frames),
14119a391c7bSWingMan Kwok 	GBENU_STATS_P7(tx_deferred_frames),
14129a391c7bSWingMan Kwok 	GBENU_STATS_P7(tx_collision_frames),
14139a391c7bSWingMan Kwok 	GBENU_STATS_P7(tx_single_coll_frames),
14149a391c7bSWingMan Kwok 	GBENU_STATS_P7(tx_mult_coll_frames),
14159a391c7bSWingMan Kwok 	GBENU_STATS_P7(tx_excessive_collisions),
14169a391c7bSWingMan Kwok 	GBENU_STATS_P7(tx_late_collisions),
14179a391c7bSWingMan Kwok 	GBENU_STATS_P7(rx_ipg_error),
14189a391c7bSWingMan Kwok 	GBENU_STATS_P7(tx_carrier_sense_errors),
14199a391c7bSWingMan Kwok 	GBENU_STATS_P7(tx_bytes),
14209a391c7bSWingMan Kwok 	GBENU_STATS_P7(tx_64B_frames),
14219a391c7bSWingMan Kwok 	GBENU_STATS_P7(tx_65_to_127B_frames),
14229a391c7bSWingMan Kwok 	GBENU_STATS_P7(tx_128_to_255B_frames),
14239a391c7bSWingMan Kwok 	GBENU_STATS_P7(tx_256_to_511B_frames),
14249a391c7bSWingMan Kwok 	GBENU_STATS_P7(tx_512_to_1023B_frames),
14259a391c7bSWingMan Kwok 	GBENU_STATS_P7(tx_1024B_frames),
14269a391c7bSWingMan Kwok 	GBENU_STATS_P7(net_bytes),
14279a391c7bSWingMan Kwok 	GBENU_STATS_P7(rx_bottom_fifo_drop),
14289a391c7bSWingMan Kwok 	GBENU_STATS_P7(rx_port_mask_drop),
14299a391c7bSWingMan Kwok 	GBENU_STATS_P7(rx_top_fifo_drop),
14309a391c7bSWingMan Kwok 	GBENU_STATS_P7(ale_rate_limit_drop),
14319a391c7bSWingMan Kwok 	GBENU_STATS_P7(ale_vid_ingress_drop),
14329a391c7bSWingMan Kwok 	GBENU_STATS_P7(ale_da_eq_sa_drop),
14339a391c7bSWingMan Kwok 	GBENU_STATS_P7(ale_unknown_ucast),
14349a391c7bSWingMan Kwok 	GBENU_STATS_P7(ale_unknown_ucast_bytes),
14359a391c7bSWingMan Kwok 	GBENU_STATS_P7(ale_unknown_mcast),
14369a391c7bSWingMan Kwok 	GBENU_STATS_P7(ale_unknown_mcast_bytes),
14379a391c7bSWingMan Kwok 	GBENU_STATS_P7(ale_unknown_bcast),
14389a391c7bSWingMan Kwok 	GBENU_STATS_P7(ale_unknown_bcast_bytes),
14395be4001eSWingMan Kwok 	GBENU_STATS_P7(ale_pol_match),
14405be4001eSWingMan Kwok 	GBENU_STATS_P7(ale_pol_match_red),
14415be4001eSWingMan Kwok 	GBENU_STATS_P7(ale_pol_match_yellow),
14429a391c7bSWingMan Kwok 	GBENU_STATS_P7(tx_mem_protect_err),
14435be4001eSWingMan Kwok 	GBENU_STATS_P7(tx_pri0_drop),
14445be4001eSWingMan Kwok 	GBENU_STATS_P7(tx_pri1_drop),
14455be4001eSWingMan Kwok 	GBENU_STATS_P7(tx_pri2_drop),
14465be4001eSWingMan Kwok 	GBENU_STATS_P7(tx_pri3_drop),
14475be4001eSWingMan Kwok 	GBENU_STATS_P7(tx_pri4_drop),
14485be4001eSWingMan Kwok 	GBENU_STATS_P7(tx_pri5_drop),
14495be4001eSWingMan Kwok 	GBENU_STATS_P7(tx_pri6_drop),
14505be4001eSWingMan Kwok 	GBENU_STATS_P7(tx_pri7_drop),
14515be4001eSWingMan Kwok 	GBENU_STATS_P7(tx_pri0_drop_bcnt),
14525be4001eSWingMan Kwok 	GBENU_STATS_P7(tx_pri1_drop_bcnt),
14535be4001eSWingMan Kwok 	GBENU_STATS_P7(tx_pri2_drop_bcnt),
14545be4001eSWingMan Kwok 	GBENU_STATS_P7(tx_pri3_drop_bcnt),
14555be4001eSWingMan Kwok 	GBENU_STATS_P7(tx_pri4_drop_bcnt),
14565be4001eSWingMan Kwok 	GBENU_STATS_P7(tx_pri5_drop_bcnt),
14575be4001eSWingMan Kwok 	GBENU_STATS_P7(tx_pri6_drop_bcnt),
14585be4001eSWingMan Kwok 	GBENU_STATS_P7(tx_pri7_drop_bcnt),
14599a391c7bSWingMan Kwok 	/* GBENU Module 8 */
14609a391c7bSWingMan Kwok 	GBENU_STATS_P8(rx_good_frames),
14619a391c7bSWingMan Kwok 	GBENU_STATS_P8(rx_broadcast_frames),
14629a391c7bSWingMan Kwok 	GBENU_STATS_P8(rx_multicast_frames),
14639a391c7bSWingMan Kwok 	GBENU_STATS_P8(rx_pause_frames),
14649a391c7bSWingMan Kwok 	GBENU_STATS_P8(rx_crc_errors),
14659a391c7bSWingMan Kwok 	GBENU_STATS_P8(rx_align_code_errors),
14669a391c7bSWingMan Kwok 	GBENU_STATS_P8(rx_oversized_frames),
14679a391c7bSWingMan Kwok 	GBENU_STATS_P8(rx_jabber_frames),
14689a391c7bSWingMan Kwok 	GBENU_STATS_P8(rx_undersized_frames),
14699a391c7bSWingMan Kwok 	GBENU_STATS_P8(rx_fragments),
14709a391c7bSWingMan Kwok 	GBENU_STATS_P8(ale_drop),
14719a391c7bSWingMan Kwok 	GBENU_STATS_P8(ale_overrun_drop),
14729a391c7bSWingMan Kwok 	GBENU_STATS_P8(rx_bytes),
14739a391c7bSWingMan Kwok 	GBENU_STATS_P8(tx_good_frames),
14749a391c7bSWingMan Kwok 	GBENU_STATS_P8(tx_broadcast_frames),
14759a391c7bSWingMan Kwok 	GBENU_STATS_P8(tx_multicast_frames),
14769a391c7bSWingMan Kwok 	GBENU_STATS_P8(tx_pause_frames),
14779a391c7bSWingMan Kwok 	GBENU_STATS_P8(tx_deferred_frames),
14789a391c7bSWingMan Kwok 	GBENU_STATS_P8(tx_collision_frames),
14799a391c7bSWingMan Kwok 	GBENU_STATS_P8(tx_single_coll_frames),
14809a391c7bSWingMan Kwok 	GBENU_STATS_P8(tx_mult_coll_frames),
14819a391c7bSWingMan Kwok 	GBENU_STATS_P8(tx_excessive_collisions),
14829a391c7bSWingMan Kwok 	GBENU_STATS_P8(tx_late_collisions),
14839a391c7bSWingMan Kwok 	GBENU_STATS_P8(rx_ipg_error),
14849a391c7bSWingMan Kwok 	GBENU_STATS_P8(tx_carrier_sense_errors),
14859a391c7bSWingMan Kwok 	GBENU_STATS_P8(tx_bytes),
14869a391c7bSWingMan Kwok 	GBENU_STATS_P8(tx_64B_frames),
14879a391c7bSWingMan Kwok 	GBENU_STATS_P8(tx_65_to_127B_frames),
14889a391c7bSWingMan Kwok 	GBENU_STATS_P8(tx_128_to_255B_frames),
14899a391c7bSWingMan Kwok 	GBENU_STATS_P8(tx_256_to_511B_frames),
14909a391c7bSWingMan Kwok 	GBENU_STATS_P8(tx_512_to_1023B_frames),
14919a391c7bSWingMan Kwok 	GBENU_STATS_P8(tx_1024B_frames),
14929a391c7bSWingMan Kwok 	GBENU_STATS_P8(net_bytes),
14939a391c7bSWingMan Kwok 	GBENU_STATS_P8(rx_bottom_fifo_drop),
14949a391c7bSWingMan Kwok 	GBENU_STATS_P8(rx_port_mask_drop),
14959a391c7bSWingMan Kwok 	GBENU_STATS_P8(rx_top_fifo_drop),
14969a391c7bSWingMan Kwok 	GBENU_STATS_P8(ale_rate_limit_drop),
14979a391c7bSWingMan Kwok 	GBENU_STATS_P8(ale_vid_ingress_drop),
14989a391c7bSWingMan Kwok 	GBENU_STATS_P8(ale_da_eq_sa_drop),
14999a391c7bSWingMan Kwok 	GBENU_STATS_P8(ale_unknown_ucast),
15009a391c7bSWingMan Kwok 	GBENU_STATS_P8(ale_unknown_ucast_bytes),
15019a391c7bSWingMan Kwok 	GBENU_STATS_P8(ale_unknown_mcast),
15029a391c7bSWingMan Kwok 	GBENU_STATS_P8(ale_unknown_mcast_bytes),
15039a391c7bSWingMan Kwok 	GBENU_STATS_P8(ale_unknown_bcast),
15049a391c7bSWingMan Kwok 	GBENU_STATS_P8(ale_unknown_bcast_bytes),
15055be4001eSWingMan Kwok 	GBENU_STATS_P8(ale_pol_match),
15065be4001eSWingMan Kwok 	GBENU_STATS_P8(ale_pol_match_red),
15075be4001eSWingMan Kwok 	GBENU_STATS_P8(ale_pol_match_yellow),
15089a391c7bSWingMan Kwok 	GBENU_STATS_P8(tx_mem_protect_err),
15095be4001eSWingMan Kwok 	GBENU_STATS_P8(tx_pri0_drop),
15105be4001eSWingMan Kwok 	GBENU_STATS_P8(tx_pri1_drop),
15115be4001eSWingMan Kwok 	GBENU_STATS_P8(tx_pri2_drop),
15125be4001eSWingMan Kwok 	GBENU_STATS_P8(tx_pri3_drop),
15135be4001eSWingMan Kwok 	GBENU_STATS_P8(tx_pri4_drop),
15145be4001eSWingMan Kwok 	GBENU_STATS_P8(tx_pri5_drop),
15155be4001eSWingMan Kwok 	GBENU_STATS_P8(tx_pri6_drop),
15165be4001eSWingMan Kwok 	GBENU_STATS_P8(tx_pri7_drop),
15175be4001eSWingMan Kwok 	GBENU_STATS_P8(tx_pri0_drop_bcnt),
15185be4001eSWingMan Kwok 	GBENU_STATS_P8(tx_pri1_drop_bcnt),
15195be4001eSWingMan Kwok 	GBENU_STATS_P8(tx_pri2_drop_bcnt),
15205be4001eSWingMan Kwok 	GBENU_STATS_P8(tx_pri3_drop_bcnt),
15215be4001eSWingMan Kwok 	GBENU_STATS_P8(tx_pri4_drop_bcnt),
15225be4001eSWingMan Kwok 	GBENU_STATS_P8(tx_pri5_drop_bcnt),
15235be4001eSWingMan Kwok 	GBENU_STATS_P8(tx_pri6_drop_bcnt),
15245be4001eSWingMan Kwok 	GBENU_STATS_P8(tx_pri7_drop_bcnt),
15259a391c7bSWingMan Kwok };
15269a391c7bSWingMan Kwok 
1527da866ba0SKaricheri, Muralidharan #define XGBE_STATS0_INFO(field)				\
1528da866ba0SKaricheri, Muralidharan {							\
1529da866ba0SKaricheri, Muralidharan 	"GBE_0:"#field, XGBE_STATS0_MODULE,		\
153090cff9e2SWingman Kwok 	FIELD_SIZEOF(struct xgbe_hw_stats, field),	\
1531da866ba0SKaricheri, Muralidharan 	offsetof(struct xgbe_hw_stats, field)		\
1532da866ba0SKaricheri, Muralidharan }
153390cff9e2SWingman Kwok 
1534da866ba0SKaricheri, Muralidharan #define XGBE_STATS1_INFO(field)				\
1535da866ba0SKaricheri, Muralidharan {							\
1536da866ba0SKaricheri, Muralidharan 	"GBE_1:"#field, XGBE_STATS1_MODULE,		\
153790cff9e2SWingman Kwok 	FIELD_SIZEOF(struct xgbe_hw_stats, field),	\
1538da866ba0SKaricheri, Muralidharan 	offsetof(struct xgbe_hw_stats, field)		\
1539da866ba0SKaricheri, Muralidharan }
154090cff9e2SWingman Kwok 
1541da866ba0SKaricheri, Muralidharan #define XGBE_STATS2_INFO(field)				\
1542da866ba0SKaricheri, Muralidharan {							\
1543da866ba0SKaricheri, Muralidharan 	"GBE_2:"#field, XGBE_STATS2_MODULE,		\
154490cff9e2SWingman Kwok 	FIELD_SIZEOF(struct xgbe_hw_stats, field),	\
1545da866ba0SKaricheri, Muralidharan 	offsetof(struct xgbe_hw_stats, field)		\
1546da866ba0SKaricheri, Muralidharan }
154790cff9e2SWingman Kwok 
154890cff9e2SWingman Kwok static const struct netcp_ethtool_stat xgbe10_et_stats[] = {
154990cff9e2SWingman Kwok 	/* GBE module 0 */
1550da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(rx_good_frames),
1551da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(rx_broadcast_frames),
1552da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(rx_multicast_frames),
1553da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(rx_oversized_frames),
1554da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(rx_undersized_frames),
1555da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(overrun_type4),
1556da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(overrun_type5),
1557da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(rx_bytes),
1558da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(tx_good_frames),
1559da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(tx_broadcast_frames),
1560da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(tx_multicast_frames),
1561da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(tx_bytes),
1562da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(tx_64byte_frames),
1563da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(tx_65_to_127byte_frames),
1564da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(tx_128_to_255byte_frames),
1565da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(tx_256_to_511byte_frames),
1566da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(tx_512_to_1023byte_frames),
1567da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(tx_1024byte_frames),
1568da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(net_bytes),
1569da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(rx_sof_overruns),
1570da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(rx_mof_overruns),
1571da866ba0SKaricheri, Muralidharan 	XGBE_STATS0_INFO(rx_dma_overruns),
157290cff9e2SWingman Kwok 	/* XGBE module 1 */
1573da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(rx_good_frames),
1574da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(rx_broadcast_frames),
1575da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(rx_multicast_frames),
1576da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(rx_pause_frames),
1577da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(rx_crc_errors),
1578da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(rx_align_code_errors),
1579da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(rx_oversized_frames),
1580da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(rx_jabber_frames),
1581da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(rx_undersized_frames),
1582da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(rx_fragments),
1583da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(overrun_type4),
1584da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(overrun_type5),
1585da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(rx_bytes),
1586da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(tx_good_frames),
1587da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(tx_broadcast_frames),
1588da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(tx_multicast_frames),
1589da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(tx_pause_frames),
1590da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(tx_deferred_frames),
1591da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(tx_collision_frames),
1592da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(tx_single_coll_frames),
1593da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(tx_mult_coll_frames),
1594da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(tx_excessive_collisions),
1595da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(tx_late_collisions),
1596da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(tx_underrun),
1597da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(tx_carrier_sense_errors),
1598da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(tx_bytes),
1599da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(tx_64byte_frames),
1600da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(tx_65_to_127byte_frames),
1601da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(tx_128_to_255byte_frames),
1602da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(tx_256_to_511byte_frames),
1603da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(tx_512_to_1023byte_frames),
1604da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(tx_1024byte_frames),
1605da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(net_bytes),
1606da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(rx_sof_overruns),
1607da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(rx_mof_overruns),
1608da866ba0SKaricheri, Muralidharan 	XGBE_STATS1_INFO(rx_dma_overruns),
160990cff9e2SWingman Kwok 	/* XGBE module 2 */
1610da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(rx_good_frames),
1611da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(rx_broadcast_frames),
1612da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(rx_multicast_frames),
1613da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(rx_pause_frames),
1614da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(rx_crc_errors),
1615da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(rx_align_code_errors),
1616da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(rx_oversized_frames),
1617da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(rx_jabber_frames),
1618da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(rx_undersized_frames),
1619da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(rx_fragments),
1620da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(overrun_type4),
1621da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(overrun_type5),
1622da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(rx_bytes),
1623da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(tx_good_frames),
1624da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(tx_broadcast_frames),
1625da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(tx_multicast_frames),
1626da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(tx_pause_frames),
1627da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(tx_deferred_frames),
1628da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(tx_collision_frames),
1629da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(tx_single_coll_frames),
1630da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(tx_mult_coll_frames),
1631da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(tx_excessive_collisions),
1632da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(tx_late_collisions),
1633da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(tx_underrun),
1634da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(tx_carrier_sense_errors),
1635da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(tx_bytes),
1636da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(tx_64byte_frames),
1637da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(tx_65_to_127byte_frames),
1638da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(tx_128_to_255byte_frames),
1639da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(tx_256_to_511byte_frames),
1640da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(tx_512_to_1023byte_frames),
1641da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(tx_1024byte_frames),
1642da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(net_bytes),
1643da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(rx_sof_overruns),
1644da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(rx_mof_overruns),
1645da866ba0SKaricheri, Muralidharan 	XGBE_STATS2_INFO(rx_dma_overruns),
164690cff9e2SWingman Kwok };
164790cff9e2SWingman Kwok 
16486f8d3f33SWingman Kwok #define for_each_intf(i, priv) \
16496f8d3f33SWingman Kwok 	list_for_each_entry((i), &(priv)->gbe_intf_head, gbe_intf_list)
16506f8d3f33SWingman Kwok 
16516f8d3f33SWingman Kwok #define for_each_sec_slave(slave, priv) \
16526f8d3f33SWingman Kwok 	list_for_each_entry((slave), &(priv)->secondary_slaves, slave_list)
16536f8d3f33SWingman Kwok 
16546f8d3f33SWingman Kwok #define first_sec_slave(priv)					\
16556f8d3f33SWingman Kwok 	list_first_entry(&priv->secondary_slaves, \
16566f8d3f33SWingman Kwok 			struct gbe_slave, slave_list)
16576f8d3f33SWingman Kwok 
16586f8d3f33SWingman Kwok static void keystone_get_drvinfo(struct net_device *ndev,
16596f8d3f33SWingman Kwok 				 struct ethtool_drvinfo *info)
16606f8d3f33SWingman Kwok {
16616f8d3f33SWingman Kwok 	strncpy(info->driver, NETCP_DRIVER_NAME, sizeof(info->driver));
16626f8d3f33SWingman Kwok 	strncpy(info->version, NETCP_DRIVER_VERSION, sizeof(info->version));
16636f8d3f33SWingman Kwok }
16646f8d3f33SWingman Kwok 
16656f8d3f33SWingman Kwok static u32 keystone_get_msglevel(struct net_device *ndev)
16666f8d3f33SWingman Kwok {
16676f8d3f33SWingman Kwok 	struct netcp_intf *netcp = netdev_priv(ndev);
16686f8d3f33SWingman Kwok 
16696f8d3f33SWingman Kwok 	return netcp->msg_enable;
16706f8d3f33SWingman Kwok }
16716f8d3f33SWingman Kwok 
16726f8d3f33SWingman Kwok static void keystone_set_msglevel(struct net_device *ndev, u32 value)
16736f8d3f33SWingman Kwok {
16746f8d3f33SWingman Kwok 	struct netcp_intf *netcp = netdev_priv(ndev);
16756f8d3f33SWingman Kwok 
16766f8d3f33SWingman Kwok 	netcp->msg_enable = value;
16776f8d3f33SWingman Kwok }
16786f8d3f33SWingman Kwok 
16796f8d3f33SWingman Kwok static void keystone_get_stat_strings(struct net_device *ndev,
16806f8d3f33SWingman Kwok 				      uint32_t stringset, uint8_t *data)
16816f8d3f33SWingman Kwok {
16826f8d3f33SWingman Kwok 	struct netcp_intf *netcp = netdev_priv(ndev);
16836f8d3f33SWingman Kwok 	struct gbe_intf *gbe_intf;
16846f8d3f33SWingman Kwok 	struct gbe_priv *gbe_dev;
16856f8d3f33SWingman Kwok 	int i;
16866f8d3f33SWingman Kwok 
16876f8d3f33SWingman Kwok 	gbe_intf = netcp_module_get_intf_data(&gbe_module, netcp);
16886f8d3f33SWingman Kwok 	if (!gbe_intf)
16896f8d3f33SWingman Kwok 		return;
16906f8d3f33SWingman Kwok 	gbe_dev = gbe_intf->gbe_dev;
16916f8d3f33SWingman Kwok 
16926f8d3f33SWingman Kwok 	switch (stringset) {
16936f8d3f33SWingman Kwok 	case ETH_SS_STATS:
16946f8d3f33SWingman Kwok 		for (i = 0; i < gbe_dev->num_et_stats; i++) {
16956f8d3f33SWingman Kwok 			memcpy(data, gbe_dev->et_stats[i].desc,
16966f8d3f33SWingman Kwok 			       ETH_GSTRING_LEN);
16976f8d3f33SWingman Kwok 			data += ETH_GSTRING_LEN;
16986f8d3f33SWingman Kwok 		}
16996f8d3f33SWingman Kwok 		break;
17006f8d3f33SWingman Kwok 	case ETH_SS_TEST:
17016f8d3f33SWingman Kwok 		break;
17026f8d3f33SWingman Kwok 	}
17036f8d3f33SWingman Kwok }
17046f8d3f33SWingman Kwok 
17056f8d3f33SWingman Kwok static int keystone_get_sset_count(struct net_device *ndev, int stringset)
17066f8d3f33SWingman Kwok {
17076f8d3f33SWingman Kwok 	struct netcp_intf *netcp = netdev_priv(ndev);
17086f8d3f33SWingman Kwok 	struct gbe_intf *gbe_intf;
17096f8d3f33SWingman Kwok 	struct gbe_priv *gbe_dev;
17106f8d3f33SWingman Kwok 
17116f8d3f33SWingman Kwok 	gbe_intf = netcp_module_get_intf_data(&gbe_module, netcp);
17126f8d3f33SWingman Kwok 	if (!gbe_intf)
17136f8d3f33SWingman Kwok 		return -EINVAL;
17146f8d3f33SWingman Kwok 	gbe_dev = gbe_intf->gbe_dev;
17156f8d3f33SWingman Kwok 
17166f8d3f33SWingman Kwok 	switch (stringset) {
17176f8d3f33SWingman Kwok 	case ETH_SS_TEST:
17186f8d3f33SWingman Kwok 		return 0;
17196f8d3f33SWingman Kwok 	case ETH_SS_STATS:
17206f8d3f33SWingman Kwok 		return gbe_dev->num_et_stats;
17216f8d3f33SWingman Kwok 	default:
17226f8d3f33SWingman Kwok 		return -EINVAL;
17236f8d3f33SWingman Kwok 	}
17246f8d3f33SWingman Kwok }
17256f8d3f33SWingman Kwok 
1726489e8a2fSWingMan Kwok static void gbe_reset_mod_stats(struct gbe_priv *gbe_dev, int stats_mod)
1727489e8a2fSWingMan Kwok {
1728489e8a2fSWingMan Kwok 	void __iomem *base = gbe_dev->hw_stats_regs[stats_mod];
1729489e8a2fSWingMan Kwok 	u32  __iomem *p_stats_entry;
1730489e8a2fSWingMan Kwok 	int i;
1731489e8a2fSWingMan Kwok 
1732489e8a2fSWingMan Kwok 	for (i = 0; i < gbe_dev->num_et_stats; i++) {
1733489e8a2fSWingMan Kwok 		if (gbe_dev->et_stats[i].type == stats_mod) {
1734489e8a2fSWingMan Kwok 			p_stats_entry = base + gbe_dev->et_stats[i].offset;
1735489e8a2fSWingMan Kwok 			gbe_dev->hw_stats[i] = 0;
1736489e8a2fSWingMan Kwok 			gbe_dev->hw_stats_prev[i] = readl(p_stats_entry);
1737489e8a2fSWingMan Kwok 		}
1738489e8a2fSWingMan Kwok 	}
1739489e8a2fSWingMan Kwok }
1740489e8a2fSWingMan Kwok 
1741fbf64c19SWingMan Kwok static inline void gbe_update_hw_stats_entry(struct gbe_priv *gbe_dev,
1742fbf64c19SWingMan Kwok 					     int et_stats_entry)
17436f8d3f33SWingman Kwok {
17446f8d3f33SWingman Kwok 	void __iomem *base = NULL;
1745489e8a2fSWingMan Kwok 	u32  __iomem *p_stats_entry;
1746489e8a2fSWingMan Kwok 	u32 curr, delta;
17476f8d3f33SWingman Kwok 
1748fbf64c19SWingMan Kwok 	/* The hw_stats_regs pointers are already
1749fbf64c19SWingMan Kwok 	 * properly set to point to the right base:
1750fbf64c19SWingMan Kwok 	 */
1751fbf64c19SWingMan Kwok 	base = gbe_dev->hw_stats_regs[gbe_dev->et_stats[et_stats_entry].type];
1752489e8a2fSWingMan Kwok 	p_stats_entry = base + gbe_dev->et_stats[et_stats_entry].offset;
1753489e8a2fSWingMan Kwok 	curr = readl(p_stats_entry);
1754489e8a2fSWingMan Kwok 	delta = curr - gbe_dev->hw_stats_prev[et_stats_entry];
1755489e8a2fSWingMan Kwok 	gbe_dev->hw_stats_prev[et_stats_entry] = curr;
1756489e8a2fSWingMan Kwok 	gbe_dev->hw_stats[et_stats_entry] += delta;
17576f8d3f33SWingman Kwok }
1758fbf64c19SWingMan Kwok 
1759fbf64c19SWingMan Kwok static void gbe_update_stats(struct gbe_priv *gbe_dev, uint64_t *data)
1760fbf64c19SWingMan Kwok {
1761fbf64c19SWingMan Kwok 	int i;
1762fbf64c19SWingMan Kwok 
1763fbf64c19SWingMan Kwok 	for (i = 0; i < gbe_dev->num_et_stats; i++) {
1764fbf64c19SWingMan Kwok 		gbe_update_hw_stats_entry(gbe_dev, i);
1765fbf64c19SWingMan Kwok 
1766fbf64c19SWingMan Kwok 		if (data)
1767fbf64c19SWingMan Kwok 			data[i] = gbe_dev->hw_stats[i];
1768fbf64c19SWingMan Kwok 	}
1769fbf64c19SWingMan Kwok }
1770fbf64c19SWingMan Kwok 
1771fbf64c19SWingMan Kwok static inline void gbe_stats_mod_visible_ver14(struct gbe_priv *gbe_dev,
1772fbf64c19SWingMan Kwok 					       int stats_mod)
1773fbf64c19SWingMan Kwok {
1774fbf64c19SWingMan Kwok 	u32 val;
1775fbf64c19SWingMan Kwok 
1776fbf64c19SWingMan Kwok 	val = readl(GBE_REG_ADDR(gbe_dev, switch_regs, stat_port_en));
1777fbf64c19SWingMan Kwok 
1778fbf64c19SWingMan Kwok 	switch (stats_mod) {
1779fbf64c19SWingMan Kwok 	case GBE_STATSA_MODULE:
1780fbf64c19SWingMan Kwok 	case GBE_STATSB_MODULE:
1781fbf64c19SWingMan Kwok 		val &= ~GBE_STATS_CD_SEL;
1782fbf64c19SWingMan Kwok 		break;
1783fbf64c19SWingMan Kwok 	case GBE_STATSC_MODULE:
1784fbf64c19SWingMan Kwok 	case GBE_STATSD_MODULE:
1785fbf64c19SWingMan Kwok 		val |= GBE_STATS_CD_SEL;
1786fbf64c19SWingMan Kwok 		break;
1787fbf64c19SWingMan Kwok 	default:
1788fbf64c19SWingMan Kwok 		return;
1789fbf64c19SWingMan Kwok 	}
1790fbf64c19SWingMan Kwok 
1791fbf64c19SWingMan Kwok 	/* make the stat module visible */
1792fbf64c19SWingMan Kwok 	writel(val, GBE_REG_ADDR(gbe_dev, switch_regs, stat_port_en));
17936f8d3f33SWingman Kwok }
17946f8d3f33SWingman Kwok 
1795489e8a2fSWingMan Kwok static void gbe_reset_mod_stats_ver14(struct gbe_priv *gbe_dev, int stats_mod)
1796489e8a2fSWingMan Kwok {
1797489e8a2fSWingMan Kwok 	gbe_stats_mod_visible_ver14(gbe_dev, stats_mod);
1798489e8a2fSWingMan Kwok 	gbe_reset_mod_stats(gbe_dev, stats_mod);
1799489e8a2fSWingMan Kwok }
1800489e8a2fSWingMan Kwok 
18016f8d3f33SWingman Kwok static void gbe_update_stats_ver14(struct gbe_priv *gbe_dev, uint64_t *data)
18026f8d3f33SWingman Kwok {
1803fbf64c19SWingMan Kwok 	u32 half_num_et_stats = (gbe_dev->num_et_stats / 2);
1804fbf64c19SWingMan Kwok 	int et_entry, j, pair;
18056f8d3f33SWingman Kwok 
18066f8d3f33SWingman Kwok 	for (pair = 0; pair < 2; pair++) {
1807fbf64c19SWingMan Kwok 		gbe_stats_mod_visible_ver14(gbe_dev, (pair ?
1808fbf64c19SWingMan Kwok 						      GBE_STATSC_MODULE :
1809fbf64c19SWingMan Kwok 						      GBE_STATSA_MODULE));
18106f8d3f33SWingman Kwok 
1811fbf64c19SWingMan Kwok 		for (j = 0; j < half_num_et_stats; j++) {
1812fbf64c19SWingMan Kwok 			et_entry = pair * half_num_et_stats + j;
1813fbf64c19SWingMan Kwok 			gbe_update_hw_stats_entry(gbe_dev, et_entry);
18146f8d3f33SWingman Kwok 
18156f8d3f33SWingman Kwok 			if (data)
1816fbf64c19SWingMan Kwok 				data[et_entry] = gbe_dev->hw_stats[et_entry];
18176f8d3f33SWingman Kwok 		}
18186f8d3f33SWingman Kwok 	}
18196f8d3f33SWingman Kwok }
18206f8d3f33SWingman Kwok 
18216f8d3f33SWingman Kwok static void keystone_get_ethtool_stats(struct net_device *ndev,
18226f8d3f33SWingman Kwok 				       struct ethtool_stats *stats,
18236f8d3f33SWingman Kwok 				       uint64_t *data)
18246f8d3f33SWingman Kwok {
18256f8d3f33SWingman Kwok 	struct netcp_intf *netcp = netdev_priv(ndev);
18266f8d3f33SWingman Kwok 	struct gbe_intf *gbe_intf;
18276f8d3f33SWingman Kwok 	struct gbe_priv *gbe_dev;
18286f8d3f33SWingman Kwok 
18296f8d3f33SWingman Kwok 	gbe_intf = netcp_module_get_intf_data(&gbe_module, netcp);
18306f8d3f33SWingman Kwok 	if (!gbe_intf)
18316f8d3f33SWingman Kwok 		return;
18326f8d3f33SWingman Kwok 
18336f8d3f33SWingman Kwok 	gbe_dev = gbe_intf->gbe_dev;
18346f8d3f33SWingman Kwok 	spin_lock_bh(&gbe_dev->hw_stats_lock);
183590cff9e2SWingman Kwok 	if (gbe_dev->ss_version == GBE_SS_VERSION_14)
18366f8d3f33SWingman Kwok 		gbe_update_stats_ver14(gbe_dev, data);
183790cff9e2SWingman Kwok 	else
183890cff9e2SWingman Kwok 		gbe_update_stats(gbe_dev, data);
18396f8d3f33SWingman Kwok 	spin_unlock_bh(&gbe_dev->hw_stats_lock);
18406f8d3f33SWingman Kwok }
18416f8d3f33SWingman Kwok 
18426f8d3f33SWingman Kwok static int keystone_get_settings(struct net_device *ndev,
18436f8d3f33SWingman Kwok 				 struct ethtool_cmd *cmd)
18446f8d3f33SWingman Kwok {
18456f8d3f33SWingman Kwok 	struct netcp_intf *netcp = netdev_priv(ndev);
18466f8d3f33SWingman Kwok 	struct phy_device *phy = ndev->phydev;
18476f8d3f33SWingman Kwok 	struct gbe_intf *gbe_intf;
18486f8d3f33SWingman Kwok 	int ret;
18496f8d3f33SWingman Kwok 
18506f8d3f33SWingman Kwok 	if (!phy)
18516f8d3f33SWingman Kwok 		return -EINVAL;
18526f8d3f33SWingman Kwok 
18536f8d3f33SWingman Kwok 	gbe_intf = netcp_module_get_intf_data(&gbe_module, netcp);
18546f8d3f33SWingman Kwok 	if (!gbe_intf)
18556f8d3f33SWingman Kwok 		return -EINVAL;
18566f8d3f33SWingman Kwok 
18576f8d3f33SWingman Kwok 	if (!gbe_intf->slave)
18586f8d3f33SWingman Kwok 		return -EINVAL;
18596f8d3f33SWingman Kwok 
18606f8d3f33SWingman Kwok 	ret = phy_ethtool_gset(phy, cmd);
18616f8d3f33SWingman Kwok 	if (!ret)
18626f8d3f33SWingman Kwok 		cmd->port = gbe_intf->slave->phy_port_t;
18636f8d3f33SWingman Kwok 
18646f8d3f33SWingman Kwok 	return ret;
18656f8d3f33SWingman Kwok }
18666f8d3f33SWingman Kwok 
18676f8d3f33SWingman Kwok static int keystone_set_settings(struct net_device *ndev,
18686f8d3f33SWingman Kwok 				 struct ethtool_cmd *cmd)
18696f8d3f33SWingman Kwok {
18706f8d3f33SWingman Kwok 	struct netcp_intf *netcp = netdev_priv(ndev);
18716f8d3f33SWingman Kwok 	struct phy_device *phy = ndev->phydev;
18726f8d3f33SWingman Kwok 	struct gbe_intf *gbe_intf;
18736f8d3f33SWingman Kwok 	u32 features = cmd->advertising & cmd->supported;
18746f8d3f33SWingman Kwok 
18756f8d3f33SWingman Kwok 	if (!phy)
18766f8d3f33SWingman Kwok 		return -EINVAL;
18776f8d3f33SWingman Kwok 
18786f8d3f33SWingman Kwok 	gbe_intf = netcp_module_get_intf_data(&gbe_module, netcp);
18796f8d3f33SWingman Kwok 	if (!gbe_intf)
18806f8d3f33SWingman Kwok 		return -EINVAL;
18816f8d3f33SWingman Kwok 
18826f8d3f33SWingman Kwok 	if (!gbe_intf->slave)
18836f8d3f33SWingman Kwok 		return -EINVAL;
18846f8d3f33SWingman Kwok 
18856f8d3f33SWingman Kwok 	if (cmd->port != gbe_intf->slave->phy_port_t) {
18866f8d3f33SWingman Kwok 		if ((cmd->port == PORT_TP) && !(features & ADVERTISED_TP))
18876f8d3f33SWingman Kwok 			return -EINVAL;
18886f8d3f33SWingman Kwok 
18896f8d3f33SWingman Kwok 		if ((cmd->port == PORT_AUI) && !(features & ADVERTISED_AUI))
18906f8d3f33SWingman Kwok 			return -EINVAL;
18916f8d3f33SWingman Kwok 
18926f8d3f33SWingman Kwok 		if ((cmd->port == PORT_BNC) && !(features & ADVERTISED_BNC))
18936f8d3f33SWingman Kwok 			return -EINVAL;
18946f8d3f33SWingman Kwok 
18956f8d3f33SWingman Kwok 		if ((cmd->port == PORT_MII) && !(features & ADVERTISED_MII))
18966f8d3f33SWingman Kwok 			return -EINVAL;
18976f8d3f33SWingman Kwok 
18986f8d3f33SWingman Kwok 		if ((cmd->port == PORT_FIBRE) && !(features & ADVERTISED_FIBRE))
18996f8d3f33SWingman Kwok 			return -EINVAL;
19006f8d3f33SWingman Kwok 	}
19016f8d3f33SWingman Kwok 
19026f8d3f33SWingman Kwok 	gbe_intf->slave->phy_port_t = cmd->port;
19036f8d3f33SWingman Kwok 	return phy_ethtool_sset(phy, cmd);
19046f8d3f33SWingman Kwok }
19056f8d3f33SWingman Kwok 
19066f8d3f33SWingman Kwok static const struct ethtool_ops keystone_ethtool_ops = {
19076f8d3f33SWingman Kwok 	.get_drvinfo		= keystone_get_drvinfo,
19086f8d3f33SWingman Kwok 	.get_link		= ethtool_op_get_link,
19096f8d3f33SWingman Kwok 	.get_msglevel		= keystone_get_msglevel,
19106f8d3f33SWingman Kwok 	.set_msglevel		= keystone_set_msglevel,
19116f8d3f33SWingman Kwok 	.get_strings		= keystone_get_stat_strings,
19126f8d3f33SWingman Kwok 	.get_sset_count		= keystone_get_sset_count,
19136f8d3f33SWingman Kwok 	.get_ethtool_stats	= keystone_get_ethtool_stats,
19146f8d3f33SWingman Kwok 	.get_settings		= keystone_get_settings,
19156f8d3f33SWingman Kwok 	.set_settings		= keystone_set_settings,
19166f8d3f33SWingman Kwok };
19176f8d3f33SWingman Kwok 
19186f8d3f33SWingman Kwok #define mac_hi(mac)	(((mac)[0] << 0) | ((mac)[1] << 8) |	\
19196f8d3f33SWingman Kwok 			 ((mac)[2] << 16) | ((mac)[3] << 24))
19206f8d3f33SWingman Kwok #define mac_lo(mac)	(((mac)[4] << 0) | ((mac)[5] << 8))
19216f8d3f33SWingman Kwok 
19226f8d3f33SWingman Kwok static void gbe_set_slave_mac(struct gbe_slave *slave,
19236f8d3f33SWingman Kwok 			      struct gbe_intf *gbe_intf)
19246f8d3f33SWingman Kwok {
19256f8d3f33SWingman Kwok 	struct net_device *ndev = gbe_intf->ndev;
19266f8d3f33SWingman Kwok 
19276f8d3f33SWingman Kwok 	writel(mac_hi(ndev->dev_addr), GBE_REG_ADDR(slave, port_regs, sa_hi));
19286f8d3f33SWingman Kwok 	writel(mac_lo(ndev->dev_addr), GBE_REG_ADDR(slave, port_regs, sa_lo));
19296f8d3f33SWingman Kwok }
19306f8d3f33SWingman Kwok 
19316f8d3f33SWingman Kwok static int gbe_get_slave_port(struct gbe_priv *priv, u32 slave_num)
19326f8d3f33SWingman Kwok {
19336f8d3f33SWingman Kwok 	if (priv->host_port == 0)
19346f8d3f33SWingman Kwok 		return slave_num + 1;
19356f8d3f33SWingman Kwok 
19366f8d3f33SWingman Kwok 	return slave_num;
19376f8d3f33SWingman Kwok }
19386f8d3f33SWingman Kwok 
19396f8d3f33SWingman Kwok static void netcp_ethss_link_state_action(struct gbe_priv *gbe_dev,
19406f8d3f33SWingman Kwok 					  struct net_device *ndev,
19416f8d3f33SWingman Kwok 					  struct gbe_slave *slave,
19426f8d3f33SWingman Kwok 					  int up)
19436f8d3f33SWingman Kwok {
19446f8d3f33SWingman Kwok 	struct phy_device *phy = slave->phy;
19456f8d3f33SWingman Kwok 	u32 mac_control = 0;
19466f8d3f33SWingman Kwok 
19476f8d3f33SWingman Kwok 	if (up) {
19486f8d3f33SWingman Kwok 		mac_control = slave->mac_control;
194990cff9e2SWingman Kwok 		if (phy && (phy->speed == SPEED_1000)) {
19506f8d3f33SWingman Kwok 			mac_control |= MACSL_GIG_MODE;
195190cff9e2SWingman Kwok 			mac_control &= ~MACSL_XGIG_MODE;
195290cff9e2SWingman Kwok 		} else if (phy && (phy->speed == SPEED_10000)) {
195390cff9e2SWingman Kwok 			mac_control |= MACSL_XGIG_MODE;
195490cff9e2SWingman Kwok 			mac_control &= ~MACSL_GIG_MODE;
195590cff9e2SWingman Kwok 		}
19566f8d3f33SWingman Kwok 
19576f8d3f33SWingman Kwok 		writel(mac_control, GBE_REG_ADDR(slave, emac_regs,
19586f8d3f33SWingman Kwok 						 mac_control));
19596f8d3f33SWingman Kwok 
19606f8d3f33SWingman Kwok 		cpsw_ale_control_set(gbe_dev->ale, slave->port_num,
19616f8d3f33SWingman Kwok 				     ALE_PORT_STATE,
19626f8d3f33SWingman Kwok 				     ALE_PORT_STATE_FORWARD);
19636f8d3f33SWingman Kwok 
19648e046d68SKaricheri, Muralidharan 		if (ndev && slave->open &&
19658e046d68SKaricheri, Muralidharan 		    slave->link_interface != SGMII_LINK_MAC_PHY &&
19668e046d68SKaricheri, Muralidharan 		    slave->link_interface != XGMII_LINK_MAC_PHY)
19676f8d3f33SWingman Kwok 			netif_carrier_on(ndev);
19686f8d3f33SWingman Kwok 	} else {
19696f8d3f33SWingman Kwok 		writel(mac_control, GBE_REG_ADDR(slave, emac_regs,
19706f8d3f33SWingman Kwok 						 mac_control));
19716f8d3f33SWingman Kwok 		cpsw_ale_control_set(gbe_dev->ale, slave->port_num,
19726f8d3f33SWingman Kwok 				     ALE_PORT_STATE,
19736f8d3f33SWingman Kwok 				     ALE_PORT_STATE_DISABLE);
19748e046d68SKaricheri, Muralidharan 		if (ndev &&
19758e046d68SKaricheri, Muralidharan 		    slave->link_interface != SGMII_LINK_MAC_PHY &&
19768e046d68SKaricheri, Muralidharan 		    slave->link_interface != XGMII_LINK_MAC_PHY)
19776f8d3f33SWingman Kwok 			netif_carrier_off(ndev);
19786f8d3f33SWingman Kwok 	}
19796f8d3f33SWingman Kwok 
19806f8d3f33SWingman Kwok 	if (phy)
19816f8d3f33SWingman Kwok 		phy_print_status(phy);
19826f8d3f33SWingman Kwok }
19836f8d3f33SWingman Kwok 
19846f8d3f33SWingman Kwok static bool gbe_phy_link_status(struct gbe_slave *slave)
19856f8d3f33SWingman Kwok {
19866f8d3f33SWingman Kwok 	 return !slave->phy || slave->phy->link;
19876f8d3f33SWingman Kwok }
19886f8d3f33SWingman Kwok 
19896f8d3f33SWingman Kwok static void netcp_ethss_update_link_state(struct gbe_priv *gbe_dev,
19906f8d3f33SWingman Kwok 					  struct gbe_slave *slave,
19916f8d3f33SWingman Kwok 					  struct net_device *ndev)
19926f8d3f33SWingman Kwok {
19936f8d3f33SWingman Kwok 	int sp = slave->slave_num;
19946f8d3f33SWingman Kwok 	int phy_link_state, sgmii_link_state = 1, link_state;
19956f8d3f33SWingman Kwok 
19966f8d3f33SWingman Kwok 	if (!slave->open)
19976f8d3f33SWingman Kwok 		return;
19986f8d3f33SWingman Kwok 
19999a391c7bSWingMan Kwok 	if (!SLAVE_LINK_IS_XGMII(slave)) {
20009a391c7bSWingMan Kwok 		if (gbe_dev->ss_version == GBE_SS_VERSION_14)
20019a391c7bSWingMan Kwok 			sgmii_link_state =
20029a391c7bSWingMan Kwok 				netcp_sgmii_get_port_link(SGMII_BASE(sp), sp);
20039a391c7bSWingMan Kwok 		else
20049a391c7bSWingMan Kwok 			sgmii_link_state =
20059a391c7bSWingMan Kwok 				netcp_sgmii_get_port_link(
20069a391c7bSWingMan Kwok 						gbe_dev->sgmii_port_regs, sp);
20079a391c7bSWingMan Kwok 	}
20089a391c7bSWingMan Kwok 
20096f8d3f33SWingman Kwok 	phy_link_state = gbe_phy_link_status(slave);
20106f8d3f33SWingman Kwok 	link_state = phy_link_state & sgmii_link_state;
20116f8d3f33SWingman Kwok 
20126f8d3f33SWingman Kwok 	if (atomic_xchg(&slave->link_state, link_state) != link_state)
20136f8d3f33SWingman Kwok 		netcp_ethss_link_state_action(gbe_dev, ndev, slave,
20146f8d3f33SWingman Kwok 					      link_state);
20156f8d3f33SWingman Kwok }
20166f8d3f33SWingman Kwok 
201790cff9e2SWingman Kwok static void xgbe_adjust_link(struct net_device *ndev)
201890cff9e2SWingman Kwok {
201990cff9e2SWingman Kwok 	struct netcp_intf *netcp = netdev_priv(ndev);
202090cff9e2SWingman Kwok 	struct gbe_intf *gbe_intf;
202190cff9e2SWingman Kwok 
202290cff9e2SWingman Kwok 	gbe_intf = netcp_module_get_intf_data(&xgbe_module, netcp);
202390cff9e2SWingman Kwok 	if (!gbe_intf)
202490cff9e2SWingman Kwok 		return;
202590cff9e2SWingman Kwok 
202690cff9e2SWingman Kwok 	netcp_ethss_update_link_state(gbe_intf->gbe_dev, gbe_intf->slave,
202790cff9e2SWingman Kwok 				      ndev);
202890cff9e2SWingman Kwok }
202990cff9e2SWingman Kwok 
20306f8d3f33SWingman Kwok static void gbe_adjust_link(struct net_device *ndev)
20316f8d3f33SWingman Kwok {
20326f8d3f33SWingman Kwok 	struct netcp_intf *netcp = netdev_priv(ndev);
20336f8d3f33SWingman Kwok 	struct gbe_intf *gbe_intf;
20346f8d3f33SWingman Kwok 
20356f8d3f33SWingman Kwok 	gbe_intf = netcp_module_get_intf_data(&gbe_module, netcp);
20366f8d3f33SWingman Kwok 	if (!gbe_intf)
20376f8d3f33SWingman Kwok 		return;
20386f8d3f33SWingman Kwok 
20396f8d3f33SWingman Kwok 	netcp_ethss_update_link_state(gbe_intf->gbe_dev, gbe_intf->slave,
20406f8d3f33SWingman Kwok 				      ndev);
20416f8d3f33SWingman Kwok }
20426f8d3f33SWingman Kwok 
20436f8d3f33SWingman Kwok static void gbe_adjust_link_sec_slaves(struct net_device *ndev)
20446f8d3f33SWingman Kwok {
20456f8d3f33SWingman Kwok 	struct gbe_priv *gbe_dev = netdev_priv(ndev);
20466f8d3f33SWingman Kwok 	struct gbe_slave *slave;
20476f8d3f33SWingman Kwok 
20486f8d3f33SWingman Kwok 	for_each_sec_slave(slave, gbe_dev)
20496f8d3f33SWingman Kwok 		netcp_ethss_update_link_state(gbe_dev, slave, NULL);
20506f8d3f33SWingman Kwok }
20516f8d3f33SWingman Kwok 
20526f8d3f33SWingman Kwok /* Reset EMAC
20536f8d3f33SWingman Kwok  * Soft reset is set and polled until clear, or until a timeout occurs
20546f8d3f33SWingman Kwok  */
20556f8d3f33SWingman Kwok static int gbe_port_reset(struct gbe_slave *slave)
20566f8d3f33SWingman Kwok {
20576f8d3f33SWingman Kwok 	u32 i, v;
20586f8d3f33SWingman Kwok 
20596f8d3f33SWingman Kwok 	/* Set the soft reset bit */
20606f8d3f33SWingman Kwok 	writel(SOFT_RESET, GBE_REG_ADDR(slave, emac_regs, soft_reset));
20616f8d3f33SWingman Kwok 
20626f8d3f33SWingman Kwok 	/* Wait for the bit to clear */
20636f8d3f33SWingman Kwok 	for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) {
20646f8d3f33SWingman Kwok 		v = readl(GBE_REG_ADDR(slave, emac_regs, soft_reset));
20656f8d3f33SWingman Kwok 		if ((v & SOFT_RESET_MASK) != SOFT_RESET)
20666f8d3f33SWingman Kwok 			return 0;
20676f8d3f33SWingman Kwok 	}
20686f8d3f33SWingman Kwok 
20696f8d3f33SWingman Kwok 	/* Timeout on the reset */
20706f8d3f33SWingman Kwok 	return GMACSL_RET_WARN_RESET_INCOMPLETE;
20716f8d3f33SWingman Kwok }
20726f8d3f33SWingman Kwok 
20736f8d3f33SWingman Kwok /* Configure EMAC */
20746f8d3f33SWingman Kwok static void gbe_port_config(struct gbe_priv *gbe_dev, struct gbe_slave *slave,
20756f8d3f33SWingman Kwok 			    int max_rx_len)
20766f8d3f33SWingman Kwok {
20779a391c7bSWingMan Kwok 	void __iomem *rx_maxlen_reg;
207890cff9e2SWingman Kwok 	u32 xgmii_mode;
207990cff9e2SWingman Kwok 
20806f8d3f33SWingman Kwok 	if (max_rx_len > NETCP_MAX_FRAME_SIZE)
20816f8d3f33SWingman Kwok 		max_rx_len = NETCP_MAX_FRAME_SIZE;
20826f8d3f33SWingman Kwok 
208390cff9e2SWingman Kwok 	/* Enable correct MII mode at SS level */
208490cff9e2SWingman Kwok 	if ((gbe_dev->ss_version == XGBE_SS_VERSION_10) &&
208590cff9e2SWingman Kwok 	    (slave->link_interface >= XGMII_LINK_MAC_PHY)) {
208690cff9e2SWingman Kwok 		xgmii_mode = readl(GBE_REG_ADDR(gbe_dev, ss_regs, control));
208790cff9e2SWingman Kwok 		xgmii_mode |= (1 << slave->slave_num);
208890cff9e2SWingman Kwok 		writel(xgmii_mode, GBE_REG_ADDR(gbe_dev, ss_regs, control));
208990cff9e2SWingman Kwok 	}
209090cff9e2SWingman Kwok 
20919a391c7bSWingMan Kwok 	if (IS_SS_ID_MU(gbe_dev))
20929a391c7bSWingMan Kwok 		rx_maxlen_reg = GBE_REG_ADDR(slave, port_regs, rx_maxlen);
20939a391c7bSWingMan Kwok 	else
20949a391c7bSWingMan Kwok 		rx_maxlen_reg = GBE_REG_ADDR(slave, emac_regs, rx_maxlen);
20959a391c7bSWingMan Kwok 
20969a391c7bSWingMan Kwok 	writel(max_rx_len, rx_maxlen_reg);
20976f8d3f33SWingman Kwok 	writel(slave->mac_control, GBE_REG_ADDR(slave, emac_regs, mac_control));
20986f8d3f33SWingman Kwok }
20996f8d3f33SWingman Kwok 
21006f8d3f33SWingman Kwok static void gbe_slave_stop(struct gbe_intf *intf)
21016f8d3f33SWingman Kwok {
21026f8d3f33SWingman Kwok 	struct gbe_priv *gbe_dev = intf->gbe_dev;
21036f8d3f33SWingman Kwok 	struct gbe_slave *slave = intf->slave;
21046f8d3f33SWingman Kwok 
21056f8d3f33SWingman Kwok 	gbe_port_reset(slave);
21066f8d3f33SWingman Kwok 	/* Disable forwarding */
21076f8d3f33SWingman Kwok 	cpsw_ale_control_set(gbe_dev->ale, slave->port_num,
21086f8d3f33SWingman Kwok 			     ALE_PORT_STATE, ALE_PORT_STATE_DISABLE);
21096f8d3f33SWingman Kwok 	cpsw_ale_del_mcast(gbe_dev->ale, intf->ndev->broadcast,
21106f8d3f33SWingman Kwok 			   1 << slave->port_num, 0, 0);
21116f8d3f33SWingman Kwok 
21126f8d3f33SWingman Kwok 	if (!slave->phy)
21136f8d3f33SWingman Kwok 		return;
21146f8d3f33SWingman Kwok 
21156f8d3f33SWingman Kwok 	phy_stop(slave->phy);
21166f8d3f33SWingman Kwok 	phy_disconnect(slave->phy);
21176f8d3f33SWingman Kwok 	slave->phy = NULL;
21186f8d3f33SWingman Kwok }
21196f8d3f33SWingman Kwok 
21206f8d3f33SWingman Kwok static void gbe_sgmii_config(struct gbe_priv *priv, struct gbe_slave *slave)
21216f8d3f33SWingman Kwok {
21226f8d3f33SWingman Kwok 	void __iomem *sgmii_port_regs;
21236f8d3f33SWingman Kwok 
21246f8d3f33SWingman Kwok 	sgmii_port_regs = priv->sgmii_port_regs;
21256f8d3f33SWingman Kwok 	if ((priv->ss_version == GBE_SS_VERSION_14) && (slave->slave_num >= 2))
21266f8d3f33SWingman Kwok 		sgmii_port_regs = priv->sgmii_port34_regs;
21276f8d3f33SWingman Kwok 
212890cff9e2SWingman Kwok 	if (!SLAVE_LINK_IS_XGMII(slave)) {
21296f8d3f33SWingman Kwok 		netcp_sgmii_reset(sgmii_port_regs, slave->slave_num);
21306f8d3f33SWingman Kwok 		netcp_sgmii_config(sgmii_port_regs, slave->slave_num,
21316f8d3f33SWingman Kwok 				   slave->link_interface);
21326f8d3f33SWingman Kwok 	}
213390cff9e2SWingman Kwok }
21346f8d3f33SWingman Kwok 
21356f8d3f33SWingman Kwok static int gbe_slave_open(struct gbe_intf *gbe_intf)
21366f8d3f33SWingman Kwok {
21376f8d3f33SWingman Kwok 	struct gbe_priv *priv = gbe_intf->gbe_dev;
21386f8d3f33SWingman Kwok 	struct gbe_slave *slave = gbe_intf->slave;
21396f8d3f33SWingman Kwok 	phy_interface_t phy_mode;
21406f8d3f33SWingman Kwok 	bool has_phy = false;
21416f8d3f33SWingman Kwok 
21426f8d3f33SWingman Kwok 	void (*hndlr)(struct net_device *) = gbe_adjust_link;
21436f8d3f33SWingman Kwok 
21446f8d3f33SWingman Kwok 	gbe_sgmii_config(priv, slave);
21456f8d3f33SWingman Kwok 	gbe_port_reset(slave);
21466f8d3f33SWingman Kwok 	gbe_port_config(priv, slave, priv->rx_packet_max);
21476f8d3f33SWingman Kwok 	gbe_set_slave_mac(slave, gbe_intf);
21486f8d3f33SWingman Kwok 	/* enable forwarding */
21496f8d3f33SWingman Kwok 	cpsw_ale_control_set(priv->ale, slave->port_num,
21506f8d3f33SWingman Kwok 			     ALE_PORT_STATE, ALE_PORT_STATE_FORWARD);
21516f8d3f33SWingman Kwok 	cpsw_ale_add_mcast(priv->ale, gbe_intf->ndev->broadcast,
21526f8d3f33SWingman Kwok 			   1 << slave->port_num, 0, 0, ALE_MCAST_FWD_2);
21536f8d3f33SWingman Kwok 
21546f8d3f33SWingman Kwok 	if (slave->link_interface == SGMII_LINK_MAC_PHY) {
21556f8d3f33SWingman Kwok 		has_phy = true;
21566f8d3f33SWingman Kwok 		phy_mode = PHY_INTERFACE_MODE_SGMII;
21576f8d3f33SWingman Kwok 		slave->phy_port_t = PORT_MII;
21586f8d3f33SWingman Kwok 	} else if (slave->link_interface == XGMII_LINK_MAC_PHY) {
21596f8d3f33SWingman Kwok 		has_phy = true;
21606f8d3f33SWingman Kwok 		phy_mode = PHY_INTERFACE_MODE_NA;
21616f8d3f33SWingman Kwok 		slave->phy_port_t = PORT_FIBRE;
21626f8d3f33SWingman Kwok 	}
21636f8d3f33SWingman Kwok 
21646f8d3f33SWingman Kwok 	if (has_phy) {
216590cff9e2SWingman Kwok 		if (priv->ss_version == XGBE_SS_VERSION_10)
216690cff9e2SWingman Kwok 			hndlr = xgbe_adjust_link;
216790cff9e2SWingman Kwok 
21686f8d3f33SWingman Kwok 		slave->phy = of_phy_connect(gbe_intf->ndev,
21696f8d3f33SWingman Kwok 					    slave->phy_node,
21706f8d3f33SWingman Kwok 					    hndlr, 0,
21716f8d3f33SWingman Kwok 					    phy_mode);
21726f8d3f33SWingman Kwok 		if (!slave->phy) {
21736f8d3f33SWingman Kwok 			dev_err(priv->dev, "phy not found on slave %d\n",
21746f8d3f33SWingman Kwok 				slave->slave_num);
21756f8d3f33SWingman Kwok 			return -ENODEV;
21766f8d3f33SWingman Kwok 		}
21776f8d3f33SWingman Kwok 		dev_dbg(priv->dev, "phy found: id is: 0x%s\n",
21786f8d3f33SWingman Kwok 			dev_name(&slave->phy->dev));
21796f8d3f33SWingman Kwok 		phy_start(slave->phy);
21806f8d3f33SWingman Kwok 		phy_read_status(slave->phy);
21816f8d3f33SWingman Kwok 	}
21826f8d3f33SWingman Kwok 	return 0;
21836f8d3f33SWingman Kwok }
21846f8d3f33SWingman Kwok 
21856f8d3f33SWingman Kwok static void gbe_init_host_port(struct gbe_priv *priv)
21866f8d3f33SWingman Kwok {
21876f8d3f33SWingman Kwok 	int bypass_en = 1;
21889a391c7bSWingMan Kwok 
21899a391c7bSWingMan Kwok 	/* Host Tx Pri */
21909a391c7bSWingMan Kwok 	if (IS_SS_ID_NU(priv))
21919a391c7bSWingMan Kwok 		writel(HOST_TX_PRI_MAP_DEFAULT,
21929a391c7bSWingMan Kwok 		       GBE_REG_ADDR(priv, host_port_regs, tx_pri_map));
21939a391c7bSWingMan Kwok 
21946f8d3f33SWingman Kwok 	/* Max length register */
21956f8d3f33SWingman Kwok 	writel(NETCP_MAX_FRAME_SIZE, GBE_REG_ADDR(priv, host_port_regs,
21966f8d3f33SWingman Kwok 						  rx_maxlen));
21976f8d3f33SWingman Kwok 
21986f8d3f33SWingman Kwok 	cpsw_ale_start(priv->ale);
21996f8d3f33SWingman Kwok 
22006f8d3f33SWingman Kwok 	if (priv->enable_ale)
22016f8d3f33SWingman Kwok 		bypass_en = 0;
22026f8d3f33SWingman Kwok 
22036f8d3f33SWingman Kwok 	cpsw_ale_control_set(priv->ale, 0, ALE_BYPASS, bypass_en);
22046f8d3f33SWingman Kwok 
22056f8d3f33SWingman Kwok 	cpsw_ale_control_set(priv->ale, 0, ALE_NO_PORT_VLAN, 1);
22066f8d3f33SWingman Kwok 
22076f8d3f33SWingman Kwok 	cpsw_ale_control_set(priv->ale, priv->host_port,
22086f8d3f33SWingman Kwok 			     ALE_PORT_STATE, ALE_PORT_STATE_FORWARD);
22096f8d3f33SWingman Kwok 
22106f8d3f33SWingman Kwok 	cpsw_ale_control_set(priv->ale, 0,
22116f8d3f33SWingman Kwok 			     ALE_PORT_UNKNOWN_VLAN_MEMBER,
22126f8d3f33SWingman Kwok 			     GBE_PORT_MASK(priv->ale_ports));
22136f8d3f33SWingman Kwok 
22146f8d3f33SWingman Kwok 	cpsw_ale_control_set(priv->ale, 0,
22156f8d3f33SWingman Kwok 			     ALE_PORT_UNKNOWN_MCAST_FLOOD,
22166f8d3f33SWingman Kwok 			     GBE_PORT_MASK(priv->ale_ports - 1));
22176f8d3f33SWingman Kwok 
22186f8d3f33SWingman Kwok 	cpsw_ale_control_set(priv->ale, 0,
22196f8d3f33SWingman Kwok 			     ALE_PORT_UNKNOWN_REG_MCAST_FLOOD,
22206f8d3f33SWingman Kwok 			     GBE_PORT_MASK(priv->ale_ports));
22216f8d3f33SWingman Kwok 
22226f8d3f33SWingman Kwok 	cpsw_ale_control_set(priv->ale, 0,
22236f8d3f33SWingman Kwok 			     ALE_PORT_UNTAGGED_EGRESS,
22246f8d3f33SWingman Kwok 			     GBE_PORT_MASK(priv->ale_ports));
22256f8d3f33SWingman Kwok }
22266f8d3f33SWingman Kwok 
22276f8d3f33SWingman Kwok static void gbe_add_mcast_addr(struct gbe_intf *gbe_intf, u8 *addr)
22286f8d3f33SWingman Kwok {
22296f8d3f33SWingman Kwok 	struct gbe_priv *gbe_dev = gbe_intf->gbe_dev;
22306f8d3f33SWingman Kwok 	u16 vlan_id;
22316f8d3f33SWingman Kwok 
22326f8d3f33SWingman Kwok 	cpsw_ale_add_mcast(gbe_dev->ale, addr,
22336f8d3f33SWingman Kwok 			   GBE_PORT_MASK(gbe_dev->ale_ports), 0, 0,
22346f8d3f33SWingman Kwok 			   ALE_MCAST_FWD_2);
22356f8d3f33SWingman Kwok 	for_each_set_bit(vlan_id, gbe_intf->active_vlans, VLAN_N_VID) {
22366f8d3f33SWingman Kwok 		cpsw_ale_add_mcast(gbe_dev->ale, addr,
22376f8d3f33SWingman Kwok 				   GBE_PORT_MASK(gbe_dev->ale_ports),
22386f8d3f33SWingman Kwok 				   ALE_VLAN, vlan_id, ALE_MCAST_FWD_2);
22396f8d3f33SWingman Kwok 	}
22406f8d3f33SWingman Kwok }
22416f8d3f33SWingman Kwok 
22426f8d3f33SWingman Kwok static void gbe_add_ucast_addr(struct gbe_intf *gbe_intf, u8 *addr)
22436f8d3f33SWingman Kwok {
22446f8d3f33SWingman Kwok 	struct gbe_priv *gbe_dev = gbe_intf->gbe_dev;
22456f8d3f33SWingman Kwok 	u16 vlan_id;
22466f8d3f33SWingman Kwok 
22476f8d3f33SWingman Kwok 	cpsw_ale_add_ucast(gbe_dev->ale, addr, gbe_dev->host_port, 0, 0);
22486f8d3f33SWingman Kwok 
22496f8d3f33SWingman Kwok 	for_each_set_bit(vlan_id, gbe_intf->active_vlans, VLAN_N_VID)
22506f8d3f33SWingman Kwok 		cpsw_ale_add_ucast(gbe_dev->ale, addr, gbe_dev->host_port,
22516f8d3f33SWingman Kwok 				   ALE_VLAN, vlan_id);
22526f8d3f33SWingman Kwok }
22536f8d3f33SWingman Kwok 
22546f8d3f33SWingman Kwok static void gbe_del_mcast_addr(struct gbe_intf *gbe_intf, u8 *addr)
22556f8d3f33SWingman Kwok {
22566f8d3f33SWingman Kwok 	struct gbe_priv *gbe_dev = gbe_intf->gbe_dev;
22576f8d3f33SWingman Kwok 	u16 vlan_id;
22586f8d3f33SWingman Kwok 
22596f8d3f33SWingman Kwok 	cpsw_ale_del_mcast(gbe_dev->ale, addr, 0, 0, 0);
22606f8d3f33SWingman Kwok 
22616f8d3f33SWingman Kwok 	for_each_set_bit(vlan_id, gbe_intf->active_vlans, VLAN_N_VID) {
22626f8d3f33SWingman Kwok 		cpsw_ale_del_mcast(gbe_dev->ale, addr, 0, ALE_VLAN, vlan_id);
22636f8d3f33SWingman Kwok 	}
22646f8d3f33SWingman Kwok }
22656f8d3f33SWingman Kwok 
22666f8d3f33SWingman Kwok static void gbe_del_ucast_addr(struct gbe_intf *gbe_intf, u8 *addr)
22676f8d3f33SWingman Kwok {
22686f8d3f33SWingman Kwok 	struct gbe_priv *gbe_dev = gbe_intf->gbe_dev;
22696f8d3f33SWingman Kwok 	u16 vlan_id;
22706f8d3f33SWingman Kwok 
22716f8d3f33SWingman Kwok 	cpsw_ale_del_ucast(gbe_dev->ale, addr, gbe_dev->host_port, 0, 0);
22726f8d3f33SWingman Kwok 
22736f8d3f33SWingman Kwok 	for_each_set_bit(vlan_id, gbe_intf->active_vlans, VLAN_N_VID) {
22746f8d3f33SWingman Kwok 		cpsw_ale_del_ucast(gbe_dev->ale, addr, gbe_dev->host_port,
22756f8d3f33SWingman Kwok 				   ALE_VLAN, vlan_id);
22766f8d3f33SWingman Kwok 	}
22776f8d3f33SWingman Kwok }
22786f8d3f33SWingman Kwok 
22796f8d3f33SWingman Kwok static int gbe_add_addr(void *intf_priv, struct netcp_addr *naddr)
22806f8d3f33SWingman Kwok {
22816f8d3f33SWingman Kwok 	struct gbe_intf *gbe_intf = intf_priv;
22826f8d3f33SWingman Kwok 	struct gbe_priv *gbe_dev = gbe_intf->gbe_dev;
22836f8d3f33SWingman Kwok 
22846f8d3f33SWingman Kwok 	dev_dbg(gbe_dev->dev, "ethss adding address %pM, type %d\n",
22856f8d3f33SWingman Kwok 		naddr->addr, naddr->type);
22866f8d3f33SWingman Kwok 
22876f8d3f33SWingman Kwok 	switch (naddr->type) {
22886f8d3f33SWingman Kwok 	case ADDR_MCAST:
22896f8d3f33SWingman Kwok 	case ADDR_BCAST:
22906f8d3f33SWingman Kwok 		gbe_add_mcast_addr(gbe_intf, naddr->addr);
22916f8d3f33SWingman Kwok 		break;
22926f8d3f33SWingman Kwok 	case ADDR_UCAST:
22936f8d3f33SWingman Kwok 	case ADDR_DEV:
22946f8d3f33SWingman Kwok 		gbe_add_ucast_addr(gbe_intf, naddr->addr);
22956f8d3f33SWingman Kwok 		break;
22966f8d3f33SWingman Kwok 	case ADDR_ANY:
22976f8d3f33SWingman Kwok 		/* nothing to do for promiscuous */
22986f8d3f33SWingman Kwok 	default:
22996f8d3f33SWingman Kwok 		break;
23006f8d3f33SWingman Kwok 	}
23016f8d3f33SWingman Kwok 
23026f8d3f33SWingman Kwok 	return 0;
23036f8d3f33SWingman Kwok }
23046f8d3f33SWingman Kwok 
23056f8d3f33SWingman Kwok static int gbe_del_addr(void *intf_priv, struct netcp_addr *naddr)
23066f8d3f33SWingman Kwok {
23076f8d3f33SWingman Kwok 	struct gbe_intf *gbe_intf = intf_priv;
23086f8d3f33SWingman Kwok 	struct gbe_priv *gbe_dev = gbe_intf->gbe_dev;
23096f8d3f33SWingman Kwok 
23106f8d3f33SWingman Kwok 	dev_dbg(gbe_dev->dev, "ethss deleting address %pM, type %d\n",
23116f8d3f33SWingman Kwok 		naddr->addr, naddr->type);
23126f8d3f33SWingman Kwok 
23136f8d3f33SWingman Kwok 	switch (naddr->type) {
23146f8d3f33SWingman Kwok 	case ADDR_MCAST:
23156f8d3f33SWingman Kwok 	case ADDR_BCAST:
23166f8d3f33SWingman Kwok 		gbe_del_mcast_addr(gbe_intf, naddr->addr);
23176f8d3f33SWingman Kwok 		break;
23186f8d3f33SWingman Kwok 	case ADDR_UCAST:
23196f8d3f33SWingman Kwok 	case ADDR_DEV:
23206f8d3f33SWingman Kwok 		gbe_del_ucast_addr(gbe_intf, naddr->addr);
23216f8d3f33SWingman Kwok 		break;
23226f8d3f33SWingman Kwok 	case ADDR_ANY:
23236f8d3f33SWingman Kwok 		/* nothing to do for promiscuous */
23246f8d3f33SWingman Kwok 	default:
23256f8d3f33SWingman Kwok 		break;
23266f8d3f33SWingman Kwok 	}
23276f8d3f33SWingman Kwok 
23286f8d3f33SWingman Kwok 	return 0;
23296f8d3f33SWingman Kwok }
23306f8d3f33SWingman Kwok 
23316f8d3f33SWingman Kwok static int gbe_add_vid(void *intf_priv, int vid)
23326f8d3f33SWingman Kwok {
23336f8d3f33SWingman Kwok 	struct gbe_intf *gbe_intf = intf_priv;
23346f8d3f33SWingman Kwok 	struct gbe_priv *gbe_dev = gbe_intf->gbe_dev;
23356f8d3f33SWingman Kwok 
23366f8d3f33SWingman Kwok 	set_bit(vid, gbe_intf->active_vlans);
23376f8d3f33SWingman Kwok 
23386f8d3f33SWingman Kwok 	cpsw_ale_add_vlan(gbe_dev->ale, vid,
23396f8d3f33SWingman Kwok 			  GBE_PORT_MASK(gbe_dev->ale_ports),
23406f8d3f33SWingman Kwok 			  GBE_MASK_NO_PORTS,
23416f8d3f33SWingman Kwok 			  GBE_PORT_MASK(gbe_dev->ale_ports),
23426f8d3f33SWingman Kwok 			  GBE_PORT_MASK(gbe_dev->ale_ports - 1));
23436f8d3f33SWingman Kwok 
23446f8d3f33SWingman Kwok 	return 0;
23456f8d3f33SWingman Kwok }
23466f8d3f33SWingman Kwok 
23476f8d3f33SWingman Kwok static int gbe_del_vid(void *intf_priv, int vid)
23486f8d3f33SWingman Kwok {
23496f8d3f33SWingman Kwok 	struct gbe_intf *gbe_intf = intf_priv;
23506f8d3f33SWingman Kwok 	struct gbe_priv *gbe_dev = gbe_intf->gbe_dev;
23516f8d3f33SWingman Kwok 
23526f8d3f33SWingman Kwok 	cpsw_ale_del_vlan(gbe_dev->ale, vid, 0);
23536f8d3f33SWingman Kwok 	clear_bit(vid, gbe_intf->active_vlans);
23546f8d3f33SWingman Kwok 	return 0;
23556f8d3f33SWingman Kwok }
23566f8d3f33SWingman Kwok 
23576f8d3f33SWingman Kwok static int gbe_ioctl(void *intf_priv, struct ifreq *req, int cmd)
23586f8d3f33SWingman Kwok {
23596f8d3f33SWingman Kwok 	struct gbe_intf *gbe_intf = intf_priv;
23606f8d3f33SWingman Kwok 	struct phy_device *phy = gbe_intf->slave->phy;
23616f8d3f33SWingman Kwok 	int ret = -EOPNOTSUPP;
23626f8d3f33SWingman Kwok 
23636f8d3f33SWingman Kwok 	if (phy)
23646f8d3f33SWingman Kwok 		ret = phy_mii_ioctl(phy, req, cmd);
23656f8d3f33SWingman Kwok 
23666f8d3f33SWingman Kwok 	return ret;
23676f8d3f33SWingman Kwok }
23686f8d3f33SWingman Kwok 
23696f8d3f33SWingman Kwok static void netcp_ethss_timer(unsigned long arg)
23706f8d3f33SWingman Kwok {
23716f8d3f33SWingman Kwok 	struct gbe_priv *gbe_dev = (struct gbe_priv *)arg;
23726f8d3f33SWingman Kwok 	struct gbe_intf *gbe_intf;
23736f8d3f33SWingman Kwok 	struct gbe_slave *slave;
23746f8d3f33SWingman Kwok 
23756f8d3f33SWingman Kwok 	/* Check & update SGMII link state of interfaces */
23766f8d3f33SWingman Kwok 	for_each_intf(gbe_intf, gbe_dev) {
23776f8d3f33SWingman Kwok 		if (!gbe_intf->slave->open)
23786f8d3f33SWingman Kwok 			continue;
23796f8d3f33SWingman Kwok 		netcp_ethss_update_link_state(gbe_dev, gbe_intf->slave,
23806f8d3f33SWingman Kwok 					      gbe_intf->ndev);
23816f8d3f33SWingman Kwok 	}
23826f8d3f33SWingman Kwok 
23836f8d3f33SWingman Kwok 	/* Check & update SGMII link state of secondary ports */
23846f8d3f33SWingman Kwok 	for_each_sec_slave(slave, gbe_dev) {
23856f8d3f33SWingman Kwok 		netcp_ethss_update_link_state(gbe_dev, slave, NULL);
23866f8d3f33SWingman Kwok 	}
23876f8d3f33SWingman Kwok 
2388c0f54edbSWingMan Kwok 	/* A timer runs as a BH, no need to block them */
2389c0f54edbSWingMan Kwok 	spin_lock(&gbe_dev->hw_stats_lock);
23906f8d3f33SWingman Kwok 
23916f8d3f33SWingman Kwok 	if (gbe_dev->ss_version == GBE_SS_VERSION_14)
23926f8d3f33SWingman Kwok 		gbe_update_stats_ver14(gbe_dev, NULL);
23936f8d3f33SWingman Kwok 	else
23946f8d3f33SWingman Kwok 		gbe_update_stats(gbe_dev, NULL);
23956f8d3f33SWingman Kwok 
2396c0f54edbSWingMan Kwok 	spin_unlock(&gbe_dev->hw_stats_lock);
23976f8d3f33SWingman Kwok 
23986f8d3f33SWingman Kwok 	gbe_dev->timer.expires	= jiffies + GBE_TIMER_INTERVAL;
23996f8d3f33SWingman Kwok 	add_timer(&gbe_dev->timer);
24006f8d3f33SWingman Kwok }
24016f8d3f33SWingman Kwok 
24026f8d3f33SWingman Kwok static int gbe_tx_hook(int order, void *data, struct netcp_packet *p_info)
24036f8d3f33SWingman Kwok {
24046f8d3f33SWingman Kwok 	struct gbe_intf *gbe_intf = data;
24056f8d3f33SWingman Kwok 
24066f8d3f33SWingman Kwok 	p_info->tx_pipe = &gbe_intf->tx_pipe;
24076f8d3f33SWingman Kwok 	return 0;
24086f8d3f33SWingman Kwok }
24096f8d3f33SWingman Kwok 
24106f8d3f33SWingman Kwok static int gbe_open(void *intf_priv, struct net_device *ndev)
24116f8d3f33SWingman Kwok {
24126f8d3f33SWingman Kwok 	struct gbe_intf *gbe_intf = intf_priv;
24136f8d3f33SWingman Kwok 	struct gbe_priv *gbe_dev = gbe_intf->gbe_dev;
24146f8d3f33SWingman Kwok 	struct netcp_intf *netcp = netdev_priv(ndev);
24156f8d3f33SWingman Kwok 	struct gbe_slave *slave = gbe_intf->slave;
24166f8d3f33SWingman Kwok 	int port_num = slave->port_num;
24176f8d3f33SWingman Kwok 	u32 reg;
24186f8d3f33SWingman Kwok 	int ret;
24196f8d3f33SWingman Kwok 
24206f8d3f33SWingman Kwok 	reg = readl(GBE_REG_ADDR(gbe_dev, switch_regs, id_ver));
24216f8d3f33SWingman Kwok 	dev_dbg(gbe_dev->dev, "initializing gbe version %d.%d (%d) GBE identification value 0x%x\n",
24226f8d3f33SWingman Kwok 		GBE_MAJOR_VERSION(reg), GBE_MINOR_VERSION(reg),
24236f8d3f33SWingman Kwok 		GBE_RTL_VERSION(reg), GBE_IDENT(reg));
24246f8d3f33SWingman Kwok 
24259a391c7bSWingMan Kwok 	/* For 10G and on NetCP 1.5, use directed to port */
24269a391c7bSWingMan Kwok 	if ((gbe_dev->ss_version == XGBE_SS_VERSION_10) || IS_SS_ID_MU(gbe_dev))
2427e170f409SKaricheri, Muralidharan 		gbe_intf->tx_pipe.flags = SWITCH_TO_PORT_IN_TAGINFO;
24286f8d3f33SWingman Kwok 
2429e170f409SKaricheri, Muralidharan 	if (gbe_dev->enable_ale)
2430e170f409SKaricheri, Muralidharan 		gbe_intf->tx_pipe.switch_to_port = 0;
2431e170f409SKaricheri, Muralidharan 	else
2432e170f409SKaricheri, Muralidharan 		gbe_intf->tx_pipe.switch_to_port = port_num;
2433e170f409SKaricheri, Muralidharan 
2434e170f409SKaricheri, Muralidharan 	dev_dbg(gbe_dev->dev,
2435e170f409SKaricheri, Muralidharan 		"opened TX channel %s: %p with to port %d, flags %d\n",
24366f8d3f33SWingman Kwok 		gbe_intf->tx_pipe.dma_chan_name,
24376f8d3f33SWingman Kwok 		gbe_intf->tx_pipe.dma_channel,
2438e170f409SKaricheri, Muralidharan 		gbe_intf->tx_pipe.switch_to_port,
2439e170f409SKaricheri, Muralidharan 		gbe_intf->tx_pipe.flags);
24406f8d3f33SWingman Kwok 
24416f8d3f33SWingman Kwok 	gbe_slave_stop(gbe_intf);
24426f8d3f33SWingman Kwok 
24436f8d3f33SWingman Kwok 	/* disable priority elevation and enable statistics on all ports */
24446f8d3f33SWingman Kwok 	writel(0, GBE_REG_ADDR(gbe_dev, switch_regs, ptype));
24456f8d3f33SWingman Kwok 
24466f8d3f33SWingman Kwok 	/* Control register */
24476f8d3f33SWingman Kwok 	writel(GBE_CTL_P0_ENABLE, GBE_REG_ADDR(gbe_dev, switch_regs, control));
24486f8d3f33SWingman Kwok 
24496f8d3f33SWingman Kwok 	/* All statistics enabled and STAT AB visible by default */
24509a391c7bSWingMan Kwok 	writel(gbe_dev->stats_en_mask, GBE_REG_ADDR(gbe_dev, switch_regs,
24516f8d3f33SWingman Kwok 						    stat_port_en));
24526f8d3f33SWingman Kwok 
24536f8d3f33SWingman Kwok 	ret = gbe_slave_open(gbe_intf);
24546f8d3f33SWingman Kwok 	if (ret)
24556f8d3f33SWingman Kwok 		goto fail;
24566f8d3f33SWingman Kwok 
24576f8d3f33SWingman Kwok 	netcp_register_txhook(netcp, GBE_TXHOOK_ORDER, gbe_tx_hook,
24586f8d3f33SWingman Kwok 			      gbe_intf);
24596f8d3f33SWingman Kwok 
24606f8d3f33SWingman Kwok 	slave->open = true;
24616f8d3f33SWingman Kwok 	netcp_ethss_update_link_state(gbe_dev, slave, ndev);
24626f8d3f33SWingman Kwok 	return 0;
24636f8d3f33SWingman Kwok 
24646f8d3f33SWingman Kwok fail:
24656f8d3f33SWingman Kwok 	gbe_slave_stop(gbe_intf);
24666f8d3f33SWingman Kwok 	return ret;
24676f8d3f33SWingman Kwok }
24686f8d3f33SWingman Kwok 
24696f8d3f33SWingman Kwok static int gbe_close(void *intf_priv, struct net_device *ndev)
24706f8d3f33SWingman Kwok {
24716f8d3f33SWingman Kwok 	struct gbe_intf *gbe_intf = intf_priv;
24726f8d3f33SWingman Kwok 	struct netcp_intf *netcp = netdev_priv(ndev);
24736f8d3f33SWingman Kwok 
24746f8d3f33SWingman Kwok 	gbe_slave_stop(gbe_intf);
24756f8d3f33SWingman Kwok 	netcp_unregister_txhook(netcp, GBE_TXHOOK_ORDER, gbe_tx_hook,
24766f8d3f33SWingman Kwok 				gbe_intf);
24776f8d3f33SWingman Kwok 
24786f8d3f33SWingman Kwok 	gbe_intf->slave->open = false;
24796f8d3f33SWingman Kwok 	atomic_set(&gbe_intf->slave->link_state, NETCP_LINK_STATE_INVALID);
24806f8d3f33SWingman Kwok 	return 0;
24816f8d3f33SWingman Kwok }
24826f8d3f33SWingman Kwok 
24836f8d3f33SWingman Kwok static int init_slave(struct gbe_priv *gbe_dev, struct gbe_slave *slave,
24846f8d3f33SWingman Kwok 		      struct device_node *node)
24856f8d3f33SWingman Kwok {
24866f8d3f33SWingman Kwok 	int port_reg_num;
24876f8d3f33SWingman Kwok 	u32 port_reg_ofs, emac_reg_ofs;
24889a391c7bSWingMan Kwok 	u32 port_reg_blk_sz, emac_reg_blk_sz;
24896f8d3f33SWingman Kwok 
24906f8d3f33SWingman Kwok 	if (of_property_read_u32(node, "slave-port", &slave->slave_num)) {
24916f8d3f33SWingman Kwok 		dev_err(gbe_dev->dev, "missing slave-port parameter\n");
24926f8d3f33SWingman Kwok 		return -EINVAL;
24936f8d3f33SWingman Kwok 	}
24946f8d3f33SWingman Kwok 
24956f8d3f33SWingman Kwok 	if (of_property_read_u32(node, "link-interface",
24966f8d3f33SWingman Kwok 				 &slave->link_interface)) {
24976f8d3f33SWingman Kwok 		dev_warn(gbe_dev->dev,
24986f8d3f33SWingman Kwok 			 "missing link-interface value defaulting to 1G mac-phy link\n");
24996f8d3f33SWingman Kwok 		slave->link_interface = SGMII_LINK_MAC_PHY;
25006f8d3f33SWingman Kwok 	}
25016f8d3f33SWingman Kwok 
25026f8d3f33SWingman Kwok 	slave->open = false;
25036f8d3f33SWingman Kwok 	slave->phy_node = of_parse_phandle(node, "phy-handle", 0);
25046f8d3f33SWingman Kwok 	slave->port_num = gbe_get_slave_port(gbe_dev, slave->slave_num);
25056f8d3f33SWingman Kwok 
250690cff9e2SWingman Kwok 	if (slave->link_interface >= XGMII_LINK_MAC_PHY)
250790cff9e2SWingman Kwok 		slave->mac_control = GBE_DEF_10G_MAC_CONTROL;
250890cff9e2SWingman Kwok 	else
25096f8d3f33SWingman Kwok 		slave->mac_control = GBE_DEF_1G_MAC_CONTROL;
25106f8d3f33SWingman Kwok 
25116f8d3f33SWingman Kwok 	/* Emac regs memmap are contiguous but port regs are not */
25126f8d3f33SWingman Kwok 	port_reg_num = slave->slave_num;
25136f8d3f33SWingman Kwok 	if (gbe_dev->ss_version == GBE_SS_VERSION_14) {
25146f8d3f33SWingman Kwok 		if (slave->slave_num > 1) {
25156f8d3f33SWingman Kwok 			port_reg_ofs = GBE13_SLAVE_PORT2_OFFSET;
25166f8d3f33SWingman Kwok 			port_reg_num -= 2;
25176f8d3f33SWingman Kwok 		} else {
25186f8d3f33SWingman Kwok 			port_reg_ofs = GBE13_SLAVE_PORT_OFFSET;
25196f8d3f33SWingman Kwok 		}
25209a391c7bSWingMan Kwok 		emac_reg_ofs = GBE13_EMAC_OFFSET;
25219a391c7bSWingMan Kwok 		port_reg_blk_sz = 0x30;
25229a391c7bSWingMan Kwok 		emac_reg_blk_sz = 0x40;
25239a391c7bSWingMan Kwok 	} else if (IS_SS_ID_MU(gbe_dev)) {
25249a391c7bSWingMan Kwok 		port_reg_ofs = GBENU_SLAVE_PORT_OFFSET;
25259a391c7bSWingMan Kwok 		emac_reg_ofs = GBENU_EMAC_OFFSET;
25269a391c7bSWingMan Kwok 		port_reg_blk_sz = 0x1000;
25279a391c7bSWingMan Kwok 		emac_reg_blk_sz = 0x1000;
252890cff9e2SWingman Kwok 	} else if (gbe_dev->ss_version == XGBE_SS_VERSION_10) {
252990cff9e2SWingman Kwok 		port_reg_ofs = XGBE10_SLAVE_PORT_OFFSET;
25309a391c7bSWingMan Kwok 		emac_reg_ofs = XGBE10_EMAC_OFFSET;
25319a391c7bSWingMan Kwok 		port_reg_blk_sz = 0x30;
25329a391c7bSWingMan Kwok 		emac_reg_blk_sz = 0x40;
25336f8d3f33SWingman Kwok 	} else {
25346f8d3f33SWingman Kwok 		dev_err(gbe_dev->dev, "unknown ethss(0x%x)\n",
25356f8d3f33SWingman Kwok 			gbe_dev->ss_version);
25366f8d3f33SWingman Kwok 		return -EINVAL;
25376f8d3f33SWingman Kwok 	}
25386f8d3f33SWingman Kwok 
253921e0e0ddSKaricheri, Muralidharan 	slave->port_regs = gbe_dev->switch_regs + port_reg_ofs +
25409a391c7bSWingMan Kwok 				(port_reg_blk_sz * port_reg_num);
254121e0e0ddSKaricheri, Muralidharan 	slave->emac_regs = gbe_dev->switch_regs + emac_reg_ofs +
25429a391c7bSWingMan Kwok 				(emac_reg_blk_sz * slave->slave_num);
25436f8d3f33SWingman Kwok 
25446f8d3f33SWingman Kwok 	if (gbe_dev->ss_version == GBE_SS_VERSION_14) {
25456f8d3f33SWingman Kwok 		/* Initialize  slave port register offsets */
25466f8d3f33SWingman Kwok 		GBE_SET_REG_OFS(slave, port_regs, port_vlan);
25476f8d3f33SWingman Kwok 		GBE_SET_REG_OFS(slave, port_regs, tx_pri_map);
25486f8d3f33SWingman Kwok 		GBE_SET_REG_OFS(slave, port_regs, sa_lo);
25496f8d3f33SWingman Kwok 		GBE_SET_REG_OFS(slave, port_regs, sa_hi);
25506f8d3f33SWingman Kwok 		GBE_SET_REG_OFS(slave, port_regs, ts_ctl);
25516f8d3f33SWingman Kwok 		GBE_SET_REG_OFS(slave, port_regs, ts_seq_ltype);
25526f8d3f33SWingman Kwok 		GBE_SET_REG_OFS(slave, port_regs, ts_vlan);
25536f8d3f33SWingman Kwok 		GBE_SET_REG_OFS(slave, port_regs, ts_ctl_ltype2);
25546f8d3f33SWingman Kwok 		GBE_SET_REG_OFS(slave, port_regs, ts_ctl2);
25556f8d3f33SWingman Kwok 
25566f8d3f33SWingman Kwok 		/* Initialize EMAC register offsets */
25576f8d3f33SWingman Kwok 		GBE_SET_REG_OFS(slave, emac_regs, mac_control);
25586f8d3f33SWingman Kwok 		GBE_SET_REG_OFS(slave, emac_regs, soft_reset);
25596f8d3f33SWingman Kwok 		GBE_SET_REG_OFS(slave, emac_regs, rx_maxlen);
25606f8d3f33SWingman Kwok 
25619a391c7bSWingMan Kwok 	} else if (IS_SS_ID_MU(gbe_dev)) {
25629a391c7bSWingMan Kwok 		/* Initialize  slave port register offsets */
25639a391c7bSWingMan Kwok 		GBENU_SET_REG_OFS(slave, port_regs, port_vlan);
25649a391c7bSWingMan Kwok 		GBENU_SET_REG_OFS(slave, port_regs, tx_pri_map);
25659a391c7bSWingMan Kwok 		GBENU_SET_REG_OFS(slave, port_regs, sa_lo);
25669a391c7bSWingMan Kwok 		GBENU_SET_REG_OFS(slave, port_regs, sa_hi);
25679a391c7bSWingMan Kwok 		GBENU_SET_REG_OFS(slave, port_regs, ts_ctl);
25689a391c7bSWingMan Kwok 		GBENU_SET_REG_OFS(slave, port_regs, ts_seq_ltype);
25699a391c7bSWingMan Kwok 		GBENU_SET_REG_OFS(slave, port_regs, ts_vlan);
25709a391c7bSWingMan Kwok 		GBENU_SET_REG_OFS(slave, port_regs, ts_ctl_ltype2);
25719a391c7bSWingMan Kwok 		GBENU_SET_REG_OFS(slave, port_regs, ts_ctl2);
25729a391c7bSWingMan Kwok 		GBENU_SET_REG_OFS(slave, port_regs, rx_maxlen);
25739a391c7bSWingMan Kwok 
25749a391c7bSWingMan Kwok 		/* Initialize EMAC register offsets */
25759a391c7bSWingMan Kwok 		GBENU_SET_REG_OFS(slave, emac_regs, mac_control);
25769a391c7bSWingMan Kwok 		GBENU_SET_REG_OFS(slave, emac_regs, soft_reset);
25779a391c7bSWingMan Kwok 
257890cff9e2SWingman Kwok 	} else if (gbe_dev->ss_version == XGBE_SS_VERSION_10) {
257990cff9e2SWingman Kwok 		/* Initialize  slave port register offsets */
258090cff9e2SWingman Kwok 		XGBE_SET_REG_OFS(slave, port_regs, port_vlan);
258190cff9e2SWingman Kwok 		XGBE_SET_REG_OFS(slave, port_regs, tx_pri_map);
258290cff9e2SWingman Kwok 		XGBE_SET_REG_OFS(slave, port_regs, sa_lo);
258390cff9e2SWingman Kwok 		XGBE_SET_REG_OFS(slave, port_regs, sa_hi);
258490cff9e2SWingman Kwok 		XGBE_SET_REG_OFS(slave, port_regs, ts_ctl);
258590cff9e2SWingman Kwok 		XGBE_SET_REG_OFS(slave, port_regs, ts_seq_ltype);
258690cff9e2SWingman Kwok 		XGBE_SET_REG_OFS(slave, port_regs, ts_vlan);
258790cff9e2SWingman Kwok 		XGBE_SET_REG_OFS(slave, port_regs, ts_ctl_ltype2);
258890cff9e2SWingman Kwok 		XGBE_SET_REG_OFS(slave, port_regs, ts_ctl2);
258990cff9e2SWingman Kwok 
259090cff9e2SWingman Kwok 		/* Initialize EMAC register offsets */
259190cff9e2SWingman Kwok 		XGBE_SET_REG_OFS(slave, emac_regs, mac_control);
259290cff9e2SWingman Kwok 		XGBE_SET_REG_OFS(slave, emac_regs, soft_reset);
259390cff9e2SWingman Kwok 		XGBE_SET_REG_OFS(slave, emac_regs, rx_maxlen);
25946f8d3f33SWingman Kwok 	}
25956f8d3f33SWingman Kwok 
25966f8d3f33SWingman Kwok 	atomic_set(&slave->link_state, NETCP_LINK_STATE_INVALID);
25976f8d3f33SWingman Kwok 	return 0;
25986f8d3f33SWingman Kwok }
25996f8d3f33SWingman Kwok 
26006f8d3f33SWingman Kwok static void init_secondary_ports(struct gbe_priv *gbe_dev,
26016f8d3f33SWingman Kwok 				 struct device_node *node)
26026f8d3f33SWingman Kwok {
26036f8d3f33SWingman Kwok 	struct device *dev = gbe_dev->dev;
26046f8d3f33SWingman Kwok 	phy_interface_t phy_mode;
26056f8d3f33SWingman Kwok 	struct gbe_priv **priv;
26066f8d3f33SWingman Kwok 	struct device_node *port;
26076f8d3f33SWingman Kwok 	struct gbe_slave *slave;
26086f8d3f33SWingman Kwok 	bool mac_phy_link = false;
26096f8d3f33SWingman Kwok 
26106f8d3f33SWingman Kwok 	for_each_child_of_node(node, port) {
26116f8d3f33SWingman Kwok 		slave = devm_kzalloc(dev, sizeof(*slave), GFP_KERNEL);
26126f8d3f33SWingman Kwok 		if (!slave) {
26136f8d3f33SWingman Kwok 			dev_err(dev,
26146f8d3f33SWingman Kwok 				"memomry alloc failed for secondary port(%s), skipping...\n",
26156f8d3f33SWingman Kwok 				port->name);
26166f8d3f33SWingman Kwok 			continue;
26176f8d3f33SWingman Kwok 		}
26186f8d3f33SWingman Kwok 
26196f8d3f33SWingman Kwok 		if (init_slave(gbe_dev, slave, port)) {
26206f8d3f33SWingman Kwok 			dev_err(dev,
26216f8d3f33SWingman Kwok 				"Failed to initialize secondary port(%s), skipping...\n",
26226f8d3f33SWingman Kwok 				port->name);
26236f8d3f33SWingman Kwok 			devm_kfree(dev, slave);
26246f8d3f33SWingman Kwok 			continue;
26256f8d3f33SWingman Kwok 		}
26266f8d3f33SWingman Kwok 
26276f8d3f33SWingman Kwok 		gbe_sgmii_config(gbe_dev, slave);
26286f8d3f33SWingman Kwok 		gbe_port_reset(slave);
26296f8d3f33SWingman Kwok 		gbe_port_config(gbe_dev, slave, gbe_dev->rx_packet_max);
26306f8d3f33SWingman Kwok 		list_add_tail(&slave->slave_list, &gbe_dev->secondary_slaves);
26316f8d3f33SWingman Kwok 		gbe_dev->num_slaves++;
263290cff9e2SWingman Kwok 		if ((slave->link_interface == SGMII_LINK_MAC_PHY) ||
263390cff9e2SWingman Kwok 		    (slave->link_interface == XGMII_LINK_MAC_PHY))
26346f8d3f33SWingman Kwok 			mac_phy_link = true;
26356f8d3f33SWingman Kwok 
26366f8d3f33SWingman Kwok 		slave->open = true;
26379a391c7bSWingMan Kwok 		if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves)
26389a391c7bSWingMan Kwok 			break;
26396f8d3f33SWingman Kwok 	}
26406f8d3f33SWingman Kwok 
26416f8d3f33SWingman Kwok 	/* of_phy_connect() is needed only for MAC-PHY interface */
26426f8d3f33SWingman Kwok 	if (!mac_phy_link)
26436f8d3f33SWingman Kwok 		return;
26446f8d3f33SWingman Kwok 
26456f8d3f33SWingman Kwok 	/* Allocate dummy netdev device for attaching to phy device */
26466f8d3f33SWingman Kwok 	gbe_dev->dummy_ndev = alloc_netdev(sizeof(gbe_dev), "dummy",
26476f8d3f33SWingman Kwok 					NET_NAME_UNKNOWN, ether_setup);
26486f8d3f33SWingman Kwok 	if (!gbe_dev->dummy_ndev) {
26496f8d3f33SWingman Kwok 		dev_err(dev,
26506f8d3f33SWingman Kwok 			"Failed to allocate dummy netdev for secondary ports, skipping phy_connect()...\n");
26516f8d3f33SWingman Kwok 		return;
26526f8d3f33SWingman Kwok 	}
26536f8d3f33SWingman Kwok 	priv = netdev_priv(gbe_dev->dummy_ndev);
26546f8d3f33SWingman Kwok 	*priv = gbe_dev;
26556f8d3f33SWingman Kwok 
26566f8d3f33SWingman Kwok 	if (slave->link_interface == SGMII_LINK_MAC_PHY) {
26576f8d3f33SWingman Kwok 		phy_mode = PHY_INTERFACE_MODE_SGMII;
26586f8d3f33SWingman Kwok 		slave->phy_port_t = PORT_MII;
26596f8d3f33SWingman Kwok 	} else {
26606f8d3f33SWingman Kwok 		phy_mode = PHY_INTERFACE_MODE_NA;
26616f8d3f33SWingman Kwok 		slave->phy_port_t = PORT_FIBRE;
26626f8d3f33SWingman Kwok 	}
26636f8d3f33SWingman Kwok 
26646f8d3f33SWingman Kwok 	for_each_sec_slave(slave, gbe_dev) {
266590cff9e2SWingman Kwok 		if ((slave->link_interface != SGMII_LINK_MAC_PHY) &&
266690cff9e2SWingman Kwok 		    (slave->link_interface != XGMII_LINK_MAC_PHY))
26676f8d3f33SWingman Kwok 			continue;
26686f8d3f33SWingman Kwok 		slave->phy =
26696f8d3f33SWingman Kwok 			of_phy_connect(gbe_dev->dummy_ndev,
26706f8d3f33SWingman Kwok 				       slave->phy_node,
26716f8d3f33SWingman Kwok 				       gbe_adjust_link_sec_slaves,
26726f8d3f33SWingman Kwok 				       0, phy_mode);
26736f8d3f33SWingman Kwok 		if (!slave->phy) {
26746f8d3f33SWingman Kwok 			dev_err(dev, "phy not found for slave %d\n",
26756f8d3f33SWingman Kwok 				slave->slave_num);
26766f8d3f33SWingman Kwok 			slave->phy = NULL;
26776f8d3f33SWingman Kwok 		} else {
26786f8d3f33SWingman Kwok 			dev_dbg(dev, "phy found: id is: 0x%s\n",
26796f8d3f33SWingman Kwok 				dev_name(&slave->phy->dev));
26806f8d3f33SWingman Kwok 			phy_start(slave->phy);
26816f8d3f33SWingman Kwok 			phy_read_status(slave->phy);
26826f8d3f33SWingman Kwok 		}
26836f8d3f33SWingman Kwok 	}
26846f8d3f33SWingman Kwok }
26856f8d3f33SWingman Kwok 
26866f8d3f33SWingman Kwok static void free_secondary_ports(struct gbe_priv *gbe_dev)
26876f8d3f33SWingman Kwok {
26886f8d3f33SWingman Kwok 	struct gbe_slave *slave;
26896f8d3f33SWingman Kwok 
26906f8d3f33SWingman Kwok 	for (;;) {
26916f8d3f33SWingman Kwok 		slave = first_sec_slave(gbe_dev);
26926f8d3f33SWingman Kwok 		if (!slave)
26936f8d3f33SWingman Kwok 			break;
26946f8d3f33SWingman Kwok 		if (slave->phy)
26956f8d3f33SWingman Kwok 			phy_disconnect(slave->phy);
26966f8d3f33SWingman Kwok 		list_del(&slave->slave_list);
26976f8d3f33SWingman Kwok 	}
26986f8d3f33SWingman Kwok 	if (gbe_dev->dummy_ndev)
26996f8d3f33SWingman Kwok 		free_netdev(gbe_dev->dummy_ndev);
27006f8d3f33SWingman Kwok }
27016f8d3f33SWingman Kwok 
270290cff9e2SWingman Kwok static int set_xgbe_ethss10_priv(struct gbe_priv *gbe_dev,
270390cff9e2SWingman Kwok 				 struct device_node *node)
270490cff9e2SWingman Kwok {
270590cff9e2SWingman Kwok 	struct resource res;
270690cff9e2SWingman Kwok 	void __iomem *regs;
270790cff9e2SWingman Kwok 	int ret, i;
270890cff9e2SWingman Kwok 
27099a391c7bSWingMan Kwok 	ret = of_address_to_resource(node, XGBE_SS_REG_INDEX, &res);
271090cff9e2SWingman Kwok 	if (ret) {
271121e0e0ddSKaricheri, Muralidharan 		dev_err(gbe_dev->dev,
271221e0e0ddSKaricheri, Muralidharan 			"Can't xlate xgbe of node(%s) ss address at %d\n",
271321e0e0ddSKaricheri, Muralidharan 			node->name, XGBE_SS_REG_INDEX);
271490cff9e2SWingman Kwok 		return ret;
271590cff9e2SWingman Kwok 	}
271690cff9e2SWingman Kwok 
271790cff9e2SWingman Kwok 	regs = devm_ioremap_resource(gbe_dev->dev, &res);
271890cff9e2SWingman Kwok 	if (IS_ERR(regs)) {
271921e0e0ddSKaricheri, Muralidharan 		dev_err(gbe_dev->dev, "Failed to map xgbe ss register base\n");
272090cff9e2SWingman Kwok 		return PTR_ERR(regs);
272190cff9e2SWingman Kwok 	}
272290cff9e2SWingman Kwok 	gbe_dev->ss_regs = regs;
272390cff9e2SWingman Kwok 
272421e0e0ddSKaricheri, Muralidharan 	ret = of_address_to_resource(node, XGBE_SM_REG_INDEX, &res);
272521e0e0ddSKaricheri, Muralidharan 	if (ret) {
272621e0e0ddSKaricheri, Muralidharan 		dev_err(gbe_dev->dev,
272721e0e0ddSKaricheri, Muralidharan 			"Can't xlate xgbe of node(%s) sm address at %d\n",
272821e0e0ddSKaricheri, Muralidharan 			node->name, XGBE_SM_REG_INDEX);
272921e0e0ddSKaricheri, Muralidharan 		return ret;
273021e0e0ddSKaricheri, Muralidharan 	}
273121e0e0ddSKaricheri, Muralidharan 
273221e0e0ddSKaricheri, Muralidharan 	regs = devm_ioremap_resource(gbe_dev->dev, &res);
273321e0e0ddSKaricheri, Muralidharan 	if (IS_ERR(regs)) {
273421e0e0ddSKaricheri, Muralidharan 		dev_err(gbe_dev->dev, "Failed to map xgbe sm register base\n");
273521e0e0ddSKaricheri, Muralidharan 		return PTR_ERR(regs);
273621e0e0ddSKaricheri, Muralidharan 	}
273721e0e0ddSKaricheri, Muralidharan 	gbe_dev->switch_regs = regs;
273821e0e0ddSKaricheri, Muralidharan 
273990cff9e2SWingman Kwok 	ret = of_address_to_resource(node, XGBE_SERDES_REG_INDEX, &res);
274090cff9e2SWingman Kwok 	if (ret) {
274121e0e0ddSKaricheri, Muralidharan 		dev_err(gbe_dev->dev,
274221e0e0ddSKaricheri, Muralidharan 			"Can't xlate xgbe serdes of node(%s) address at %d\n",
274321e0e0ddSKaricheri, Muralidharan 			node->name, XGBE_SERDES_REG_INDEX);
274490cff9e2SWingman Kwok 		return ret;
274590cff9e2SWingman Kwok 	}
274690cff9e2SWingman Kwok 
274790cff9e2SWingman Kwok 	regs = devm_ioremap_resource(gbe_dev->dev, &res);
274890cff9e2SWingman Kwok 	if (IS_ERR(regs)) {
274990cff9e2SWingman Kwok 		dev_err(gbe_dev->dev, "Failed to map xgbe serdes register base\n");
275090cff9e2SWingman Kwok 		return PTR_ERR(regs);
275190cff9e2SWingman Kwok 	}
275290cff9e2SWingman Kwok 	gbe_dev->xgbe_serdes_regs = regs;
275390cff9e2SWingman Kwok 
2754489e8a2fSWingMan Kwok 	gbe_dev->num_stats_mods = gbe_dev->max_num_ports;
2755208c6b9aSWingMan Kwok 	gbe_dev->et_stats = xgbe10_et_stats;
2756208c6b9aSWingMan Kwok 	gbe_dev->num_et_stats = ARRAY_SIZE(xgbe10_et_stats);
2757208c6b9aSWingMan Kwok 
275890cff9e2SWingman Kwok 	gbe_dev->hw_stats = devm_kzalloc(gbe_dev->dev,
2759208c6b9aSWingMan Kwok 					 gbe_dev->num_et_stats * sizeof(u64),
276090cff9e2SWingman Kwok 					 GFP_KERNEL);
276190cff9e2SWingman Kwok 	if (!gbe_dev->hw_stats) {
276290cff9e2SWingman Kwok 		dev_err(gbe_dev->dev, "hw_stats memory allocation failed\n");
276390cff9e2SWingman Kwok 		return -ENOMEM;
276490cff9e2SWingman Kwok 	}
276590cff9e2SWingman Kwok 
2766489e8a2fSWingMan Kwok 	gbe_dev->hw_stats_prev =
2767489e8a2fSWingMan Kwok 		devm_kzalloc(gbe_dev->dev,
2768489e8a2fSWingMan Kwok 			     gbe_dev->num_et_stats * sizeof(u32),
2769489e8a2fSWingMan Kwok 			     GFP_KERNEL);
2770489e8a2fSWingMan Kwok 	if (!gbe_dev->hw_stats_prev) {
2771489e8a2fSWingMan Kwok 		dev_err(gbe_dev->dev,
2772489e8a2fSWingMan Kwok 			"hw_stats_prev memory allocation failed\n");
2773489e8a2fSWingMan Kwok 		return -ENOMEM;
2774489e8a2fSWingMan Kwok 	}
2775489e8a2fSWingMan Kwok 
277690cff9e2SWingman Kwok 	gbe_dev->ss_version = XGBE_SS_VERSION_10;
277790cff9e2SWingman Kwok 	gbe_dev->sgmii_port_regs = gbe_dev->ss_regs +
277890cff9e2SWingman Kwok 					XGBE10_SGMII_MODULE_OFFSET;
277990cff9e2SWingman Kwok 	gbe_dev->host_port_regs = gbe_dev->ss_regs + XGBE10_HOST_PORT_OFFSET;
278090cff9e2SWingman Kwok 
27819a391c7bSWingMan Kwok 	for (i = 0; i < gbe_dev->max_num_ports; i++)
278221e0e0ddSKaricheri, Muralidharan 		gbe_dev->hw_stats_regs[i] = gbe_dev->switch_regs +
278390cff9e2SWingman Kwok 			XGBE10_HW_STATS_OFFSET + (GBE_HW_STATS_REG_MAP_SZ * i);
278490cff9e2SWingman Kwok 
27859a391c7bSWingMan Kwok 	gbe_dev->ale_reg = gbe_dev->switch_regs + XGBE10_ALE_OFFSET;
27869a391c7bSWingMan Kwok 	gbe_dev->ale_ports = gbe_dev->max_num_ports;
278790cff9e2SWingman Kwok 	gbe_dev->host_port = XGBE10_HOST_PORT_NUM;
278890cff9e2SWingman Kwok 	gbe_dev->ale_entries = XGBE10_NUM_ALE_ENTRIES;
27899a391c7bSWingMan Kwok 	gbe_dev->stats_en_mask = (1 << (gbe_dev->max_num_ports)) - 1;
279090cff9e2SWingman Kwok 
279190cff9e2SWingman Kwok 	/* Subsystem registers */
279290cff9e2SWingman Kwok 	XGBE_SET_REG_OFS(gbe_dev, ss_regs, id_ver);
279390cff9e2SWingman Kwok 	XGBE_SET_REG_OFS(gbe_dev, ss_regs, control);
279490cff9e2SWingman Kwok 
279590cff9e2SWingman Kwok 	/* Switch module registers */
279690cff9e2SWingman Kwok 	XGBE_SET_REG_OFS(gbe_dev, switch_regs, id_ver);
279790cff9e2SWingman Kwok 	XGBE_SET_REG_OFS(gbe_dev, switch_regs, control);
279890cff9e2SWingman Kwok 	XGBE_SET_REG_OFS(gbe_dev, switch_regs, ptype);
279990cff9e2SWingman Kwok 	XGBE_SET_REG_OFS(gbe_dev, switch_regs, stat_port_en);
280090cff9e2SWingman Kwok 	XGBE_SET_REG_OFS(gbe_dev, switch_regs, flow_control);
280190cff9e2SWingman Kwok 
280290cff9e2SWingman Kwok 	/* Host port registers */
280390cff9e2SWingman Kwok 	XGBE_SET_REG_OFS(gbe_dev, host_port_regs, port_vlan);
280490cff9e2SWingman Kwok 	XGBE_SET_REG_OFS(gbe_dev, host_port_regs, tx_pri_map);
280590cff9e2SWingman Kwok 	XGBE_SET_REG_OFS(gbe_dev, host_port_regs, rx_maxlen);
280690cff9e2SWingman Kwok 	return 0;
280790cff9e2SWingman Kwok }
280890cff9e2SWingman Kwok 
28096f8d3f33SWingman Kwok static int get_gbe_resource_version(struct gbe_priv *gbe_dev,
28106f8d3f33SWingman Kwok 				    struct device_node *node)
28116f8d3f33SWingman Kwok {
28126f8d3f33SWingman Kwok 	struct resource res;
28136f8d3f33SWingman Kwok 	void __iomem *regs;
28146f8d3f33SWingman Kwok 	int ret;
28156f8d3f33SWingman Kwok 
281621e0e0ddSKaricheri, Muralidharan 	ret = of_address_to_resource(node, GBE_SS_REG_INDEX, &res);
28176f8d3f33SWingman Kwok 	if (ret) {
281821e0e0ddSKaricheri, Muralidharan 		dev_err(gbe_dev->dev,
281921e0e0ddSKaricheri, Muralidharan 			"Can't translate of node(%s) of gbe ss address at %d\n",
282021e0e0ddSKaricheri, Muralidharan 			node->name, GBE_SS_REG_INDEX);
28216f8d3f33SWingman Kwok 		return ret;
28226f8d3f33SWingman Kwok 	}
28236f8d3f33SWingman Kwok 
28246f8d3f33SWingman Kwok 	regs = devm_ioremap_resource(gbe_dev->dev, &res);
28256f8d3f33SWingman Kwok 	if (IS_ERR(regs)) {
28266f8d3f33SWingman Kwok 		dev_err(gbe_dev->dev, "Failed to map gbe register base\n");
28276f8d3f33SWingman Kwok 		return PTR_ERR(regs);
28286f8d3f33SWingman Kwok 	}
28296f8d3f33SWingman Kwok 	gbe_dev->ss_regs = regs;
28306f8d3f33SWingman Kwok 	gbe_dev->ss_version = readl(gbe_dev->ss_regs);
28316f8d3f33SWingman Kwok 	return 0;
28326f8d3f33SWingman Kwok }
28336f8d3f33SWingman Kwok 
28346f8d3f33SWingman Kwok static int set_gbe_ethss14_priv(struct gbe_priv *gbe_dev,
28356f8d3f33SWingman Kwok 				struct device_node *node)
28366f8d3f33SWingman Kwok {
283721e0e0ddSKaricheri, Muralidharan 	struct resource res;
28386f8d3f33SWingman Kwok 	void __iomem *regs;
283921e0e0ddSKaricheri, Muralidharan 	int i, ret;
284021e0e0ddSKaricheri, Muralidharan 
284121e0e0ddSKaricheri, Muralidharan 	ret = of_address_to_resource(node, GBE_SGMII34_REG_INDEX, &res);
284221e0e0ddSKaricheri, Muralidharan 	if (ret) {
284321e0e0ddSKaricheri, Muralidharan 		dev_err(gbe_dev->dev,
284421e0e0ddSKaricheri, Muralidharan 			"Can't translate of gbe node(%s) address at index %d\n",
284521e0e0ddSKaricheri, Muralidharan 			node->name, GBE_SGMII34_REG_INDEX);
284621e0e0ddSKaricheri, Muralidharan 		return ret;
284721e0e0ddSKaricheri, Muralidharan 	}
284821e0e0ddSKaricheri, Muralidharan 
284921e0e0ddSKaricheri, Muralidharan 	regs = devm_ioremap_resource(gbe_dev->dev, &res);
285021e0e0ddSKaricheri, Muralidharan 	if (IS_ERR(regs)) {
285121e0e0ddSKaricheri, Muralidharan 		dev_err(gbe_dev->dev,
285221e0e0ddSKaricheri, Muralidharan 			"Failed to map gbe sgmii port34 register base\n");
285321e0e0ddSKaricheri, Muralidharan 		return PTR_ERR(regs);
285421e0e0ddSKaricheri, Muralidharan 	}
285521e0e0ddSKaricheri, Muralidharan 	gbe_dev->sgmii_port34_regs = regs;
285621e0e0ddSKaricheri, Muralidharan 
285721e0e0ddSKaricheri, Muralidharan 	ret = of_address_to_resource(node, GBE_SM_REG_INDEX, &res);
285821e0e0ddSKaricheri, Muralidharan 	if (ret) {
285921e0e0ddSKaricheri, Muralidharan 		dev_err(gbe_dev->dev,
286021e0e0ddSKaricheri, Muralidharan 			"Can't translate of gbe node(%s) address at index %d\n",
286121e0e0ddSKaricheri, Muralidharan 			node->name, GBE_SM_REG_INDEX);
286221e0e0ddSKaricheri, Muralidharan 		return ret;
286321e0e0ddSKaricheri, Muralidharan 	}
286421e0e0ddSKaricheri, Muralidharan 
286521e0e0ddSKaricheri, Muralidharan 	regs = devm_ioremap_resource(gbe_dev->dev, &res);
286621e0e0ddSKaricheri, Muralidharan 	if (IS_ERR(regs)) {
286721e0e0ddSKaricheri, Muralidharan 		dev_err(gbe_dev->dev,
286821e0e0ddSKaricheri, Muralidharan 			"Failed to map gbe switch module register base\n");
286921e0e0ddSKaricheri, Muralidharan 		return PTR_ERR(regs);
287021e0e0ddSKaricheri, Muralidharan 	}
287121e0e0ddSKaricheri, Muralidharan 	gbe_dev->switch_regs = regs;
28726f8d3f33SWingman Kwok 
2873489e8a2fSWingMan Kwok 	gbe_dev->num_stats_mods = gbe_dev->max_num_slaves;
2874208c6b9aSWingMan Kwok 	gbe_dev->et_stats = gbe13_et_stats;
2875208c6b9aSWingMan Kwok 	gbe_dev->num_et_stats = ARRAY_SIZE(gbe13_et_stats);
2876208c6b9aSWingMan Kwok 
28776f8d3f33SWingman Kwok 	gbe_dev->hw_stats = devm_kzalloc(gbe_dev->dev,
2878208c6b9aSWingMan Kwok 					 gbe_dev->num_et_stats * sizeof(u64),
28796f8d3f33SWingman Kwok 					 GFP_KERNEL);
28806f8d3f33SWingman Kwok 	if (!gbe_dev->hw_stats) {
28816f8d3f33SWingman Kwok 		dev_err(gbe_dev->dev, "hw_stats memory allocation failed\n");
28826f8d3f33SWingman Kwok 		return -ENOMEM;
28836f8d3f33SWingman Kwok 	}
28846f8d3f33SWingman Kwok 
2885489e8a2fSWingMan Kwok 	gbe_dev->hw_stats_prev =
2886489e8a2fSWingMan Kwok 		devm_kzalloc(gbe_dev->dev,
2887489e8a2fSWingMan Kwok 			     gbe_dev->num_et_stats * sizeof(u32),
2888489e8a2fSWingMan Kwok 			     GFP_KERNEL);
2889489e8a2fSWingMan Kwok 	if (!gbe_dev->hw_stats_prev) {
2890489e8a2fSWingMan Kwok 		dev_err(gbe_dev->dev,
2891489e8a2fSWingMan Kwok 			"hw_stats_prev memory allocation failed\n");
2892489e8a2fSWingMan Kwok 		return -ENOMEM;
2893489e8a2fSWingMan Kwok 	}
2894489e8a2fSWingMan Kwok 
289521e0e0ddSKaricheri, Muralidharan 	gbe_dev->sgmii_port_regs = gbe_dev->ss_regs + GBE13_SGMII_MODULE_OFFSET;
289621e0e0ddSKaricheri, Muralidharan 	gbe_dev->host_port_regs = gbe_dev->switch_regs + GBE13_HOST_PORT_OFFSET;
28976f8d3f33SWingman Kwok 
2898a94bcd09SWingMan Kwok 	/* K2HK has only 2 hw stats modules visible at a time, so
2899a94bcd09SWingMan Kwok 	 * module 0 & 2 points to one base and
2900a94bcd09SWingMan Kwok 	 * module 1 & 3 points to the other base
2901a94bcd09SWingMan Kwok 	 */
29029a391c7bSWingMan Kwok 	for (i = 0; i < gbe_dev->max_num_slaves; i++) {
290321e0e0ddSKaricheri, Muralidharan 		gbe_dev->hw_stats_regs[i] =
290421e0e0ddSKaricheri, Muralidharan 			gbe_dev->switch_regs + GBE13_HW_STATS_OFFSET +
2905a94bcd09SWingMan Kwok 			(GBE_HW_STATS_REG_MAP_SZ * (i & 0x1));
290621e0e0ddSKaricheri, Muralidharan 	}
29076f8d3f33SWingman Kwok 
290821e0e0ddSKaricheri, Muralidharan 	gbe_dev->ale_reg = gbe_dev->switch_regs + GBE13_ALE_OFFSET;
29099a391c7bSWingMan Kwok 	gbe_dev->ale_ports = gbe_dev->max_num_ports;
29106f8d3f33SWingman Kwok 	gbe_dev->host_port = GBE13_HOST_PORT_NUM;
29116f8d3f33SWingman Kwok 	gbe_dev->ale_entries = GBE13_NUM_ALE_ENTRIES;
29129a391c7bSWingMan Kwok 	gbe_dev->stats_en_mask = GBE13_REG_VAL_STAT_ENABLE_ALL;
29136f8d3f33SWingman Kwok 
29146f8d3f33SWingman Kwok 	/* Subsystem registers */
29156f8d3f33SWingman Kwok 	GBE_SET_REG_OFS(gbe_dev, ss_regs, id_ver);
29166f8d3f33SWingman Kwok 
29176f8d3f33SWingman Kwok 	/* Switch module registers */
29186f8d3f33SWingman Kwok 	GBE_SET_REG_OFS(gbe_dev, switch_regs, id_ver);
29196f8d3f33SWingman Kwok 	GBE_SET_REG_OFS(gbe_dev, switch_regs, control);
29206f8d3f33SWingman Kwok 	GBE_SET_REG_OFS(gbe_dev, switch_regs, soft_reset);
29216f8d3f33SWingman Kwok 	GBE_SET_REG_OFS(gbe_dev, switch_regs, stat_port_en);
29226f8d3f33SWingman Kwok 	GBE_SET_REG_OFS(gbe_dev, switch_regs, ptype);
29236f8d3f33SWingman Kwok 	GBE_SET_REG_OFS(gbe_dev, switch_regs, flow_control);
29246f8d3f33SWingman Kwok 
29256f8d3f33SWingman Kwok 	/* Host port registers */
29266f8d3f33SWingman Kwok 	GBE_SET_REG_OFS(gbe_dev, host_port_regs, port_vlan);
29276f8d3f33SWingman Kwok 	GBE_SET_REG_OFS(gbe_dev, host_port_regs, rx_maxlen);
29286f8d3f33SWingman Kwok 	return 0;
29296f8d3f33SWingman Kwok }
29306f8d3f33SWingman Kwok 
29319a391c7bSWingMan Kwok static int set_gbenu_ethss_priv(struct gbe_priv *gbe_dev,
29329a391c7bSWingMan Kwok 				struct device_node *node)
29339a391c7bSWingMan Kwok {
29349a391c7bSWingMan Kwok 	struct resource res;
29359a391c7bSWingMan Kwok 	void __iomem *regs;
29369a391c7bSWingMan Kwok 	int i, ret;
29379a391c7bSWingMan Kwok 
2938489e8a2fSWingMan Kwok 	gbe_dev->num_stats_mods = gbe_dev->max_num_ports;
2939208c6b9aSWingMan Kwok 	gbe_dev->et_stats = gbenu_et_stats;
2940208c6b9aSWingMan Kwok 
2941208c6b9aSWingMan Kwok 	if (IS_SS_ID_NU(gbe_dev))
2942208c6b9aSWingMan Kwok 		gbe_dev->num_et_stats = GBENU_ET_STATS_HOST_SIZE +
2943208c6b9aSWingMan Kwok 			(gbe_dev->max_num_slaves * GBENU_ET_STATS_PORT_SIZE);
2944208c6b9aSWingMan Kwok 	else
2945208c6b9aSWingMan Kwok 		gbe_dev->num_et_stats = GBENU_ET_STATS_HOST_SIZE +
2946208c6b9aSWingMan Kwok 					GBENU_ET_STATS_PORT_SIZE;
2947208c6b9aSWingMan Kwok 
29489a391c7bSWingMan Kwok 	gbe_dev->hw_stats = devm_kzalloc(gbe_dev->dev,
2949208c6b9aSWingMan Kwok 					 gbe_dev->num_et_stats * sizeof(u64),
29509a391c7bSWingMan Kwok 					 GFP_KERNEL);
29519a391c7bSWingMan Kwok 	if (!gbe_dev->hw_stats) {
29529a391c7bSWingMan Kwok 		dev_err(gbe_dev->dev, "hw_stats memory allocation failed\n");
29539a391c7bSWingMan Kwok 		return -ENOMEM;
29549a391c7bSWingMan Kwok 	}
29559a391c7bSWingMan Kwok 
2956489e8a2fSWingMan Kwok 	gbe_dev->hw_stats_prev =
2957489e8a2fSWingMan Kwok 		devm_kzalloc(gbe_dev->dev,
2958489e8a2fSWingMan Kwok 			     gbe_dev->num_et_stats * sizeof(u32),
2959489e8a2fSWingMan Kwok 			     GFP_KERNEL);
2960489e8a2fSWingMan Kwok 	if (!gbe_dev->hw_stats_prev) {
2961489e8a2fSWingMan Kwok 		dev_err(gbe_dev->dev,
2962489e8a2fSWingMan Kwok 			"hw_stats_prev memory allocation failed\n");
2963489e8a2fSWingMan Kwok 		return -ENOMEM;
2964489e8a2fSWingMan Kwok 	}
2965489e8a2fSWingMan Kwok 
29669a391c7bSWingMan Kwok 	ret = of_address_to_resource(node, GBENU_SM_REG_INDEX, &res);
29679a391c7bSWingMan Kwok 	if (ret) {
29689a391c7bSWingMan Kwok 		dev_err(gbe_dev->dev,
29699a391c7bSWingMan Kwok 			"Can't translate of gbenu node(%s) addr at index %d\n",
29709a391c7bSWingMan Kwok 			node->name, GBENU_SM_REG_INDEX);
29719a391c7bSWingMan Kwok 		return ret;
29729a391c7bSWingMan Kwok 	}
29739a391c7bSWingMan Kwok 
29749a391c7bSWingMan Kwok 	regs = devm_ioremap_resource(gbe_dev->dev, &res);
29759a391c7bSWingMan Kwok 	if (IS_ERR(regs)) {
29769a391c7bSWingMan Kwok 		dev_err(gbe_dev->dev,
29779a391c7bSWingMan Kwok 			"Failed to map gbenu switch module register base\n");
29789a391c7bSWingMan Kwok 		return PTR_ERR(regs);
29799a391c7bSWingMan Kwok 	}
29809a391c7bSWingMan Kwok 	gbe_dev->switch_regs = regs;
29819a391c7bSWingMan Kwok 
29829a391c7bSWingMan Kwok 	gbe_dev->sgmii_port_regs = gbe_dev->ss_regs + GBENU_SGMII_MODULE_OFFSET;
29839a391c7bSWingMan Kwok 	gbe_dev->host_port_regs = gbe_dev->switch_regs + GBENU_HOST_PORT_OFFSET;
29849a391c7bSWingMan Kwok 
29859a391c7bSWingMan Kwok 	for (i = 0; i < (gbe_dev->max_num_ports); i++)
29869a391c7bSWingMan Kwok 		gbe_dev->hw_stats_regs[i] = gbe_dev->switch_regs +
29879a391c7bSWingMan Kwok 			GBENU_HW_STATS_OFFSET + (GBENU_HW_STATS_REG_MAP_SZ * i);
29889a391c7bSWingMan Kwok 
29899a391c7bSWingMan Kwok 	gbe_dev->ale_reg = gbe_dev->switch_regs + GBENU_ALE_OFFSET;
29909a391c7bSWingMan Kwok 	gbe_dev->ale_ports = gbe_dev->max_num_ports;
29919a391c7bSWingMan Kwok 	gbe_dev->host_port = GBENU_HOST_PORT_NUM;
29929a391c7bSWingMan Kwok 	gbe_dev->ale_entries = GBE13_NUM_ALE_ENTRIES;
29939a391c7bSWingMan Kwok 	gbe_dev->stats_en_mask = (1 << (gbe_dev->max_num_ports)) - 1;
29949a391c7bSWingMan Kwok 
29959a391c7bSWingMan Kwok 	/* Subsystem registers */
29969a391c7bSWingMan Kwok 	GBENU_SET_REG_OFS(gbe_dev, ss_regs, id_ver);
29979a391c7bSWingMan Kwok 
29989a391c7bSWingMan Kwok 	/* Switch module registers */
29999a391c7bSWingMan Kwok 	GBENU_SET_REG_OFS(gbe_dev, switch_regs, id_ver);
30009a391c7bSWingMan Kwok 	GBENU_SET_REG_OFS(gbe_dev, switch_regs, control);
30019a391c7bSWingMan Kwok 	GBENU_SET_REG_OFS(gbe_dev, switch_regs, stat_port_en);
30029a391c7bSWingMan Kwok 	GBENU_SET_REG_OFS(gbe_dev, switch_regs, ptype);
30039a391c7bSWingMan Kwok 
30049a391c7bSWingMan Kwok 	/* Host port registers */
30059a391c7bSWingMan Kwok 	GBENU_SET_REG_OFS(gbe_dev, host_port_regs, port_vlan);
30069a391c7bSWingMan Kwok 	GBENU_SET_REG_OFS(gbe_dev, host_port_regs, rx_maxlen);
30079a391c7bSWingMan Kwok 
30089a391c7bSWingMan Kwok 	/* For NU only.  2U does not need tx_pri_map.
30099a391c7bSWingMan Kwok 	 * NU cppi port 0 tx pkt streaming interface has (n-1)*8 egress threads
30109a391c7bSWingMan Kwok 	 * while 2U has only 1 such thread
30119a391c7bSWingMan Kwok 	 */
30129a391c7bSWingMan Kwok 	GBENU_SET_REG_OFS(gbe_dev, host_port_regs, tx_pri_map);
30139a391c7bSWingMan Kwok 	return 0;
30149a391c7bSWingMan Kwok }
30159a391c7bSWingMan Kwok 
30166f8d3f33SWingman Kwok static int gbe_probe(struct netcp_device *netcp_device, struct device *dev,
30176f8d3f33SWingman Kwok 		     struct device_node *node, void **inst_priv)
30186f8d3f33SWingman Kwok {
30196f8d3f33SWingman Kwok 	struct device_node *interfaces, *interface;
30206f8d3f33SWingman Kwok 	struct device_node *secondary_ports;
30216f8d3f33SWingman Kwok 	struct cpsw_ale_params ale_params;
30226f8d3f33SWingman Kwok 	struct gbe_priv *gbe_dev;
30236f8d3f33SWingman Kwok 	u32 slave_num;
3024489e8a2fSWingMan Kwok 	int i, ret = 0;
30256f8d3f33SWingman Kwok 
30266f8d3f33SWingman Kwok 	if (!node) {
30276f8d3f33SWingman Kwok 		dev_err(dev, "device tree info unavailable\n");
30286f8d3f33SWingman Kwok 		return -ENODEV;
30296f8d3f33SWingman Kwok 	}
30306f8d3f33SWingman Kwok 
30316f8d3f33SWingman Kwok 	gbe_dev = devm_kzalloc(dev, sizeof(struct gbe_priv), GFP_KERNEL);
30326f8d3f33SWingman Kwok 	if (!gbe_dev)
30336f8d3f33SWingman Kwok 		return -ENOMEM;
30346f8d3f33SWingman Kwok 
30359a391c7bSWingMan Kwok 	if (of_device_is_compatible(node, "ti,netcp-gbe-5") ||
30369a391c7bSWingMan Kwok 	    of_device_is_compatible(node, "ti,netcp-gbe")) {
30379a391c7bSWingMan Kwok 		gbe_dev->max_num_slaves = 4;
30389a391c7bSWingMan Kwok 	} else if (of_device_is_compatible(node, "ti,netcp-gbe-9")) {
30399a391c7bSWingMan Kwok 		gbe_dev->max_num_slaves = 8;
30409a391c7bSWingMan Kwok 	} else if (of_device_is_compatible(node, "ti,netcp-gbe-2")) {
30419a391c7bSWingMan Kwok 		gbe_dev->max_num_slaves = 1;
30429a391c7bSWingMan Kwok 	} else if (of_device_is_compatible(node, "ti,netcp-xgbe")) {
30439a391c7bSWingMan Kwok 		gbe_dev->max_num_slaves = 2;
30449a391c7bSWingMan Kwok 	} else {
30459a391c7bSWingMan Kwok 		dev_err(dev, "device tree node for unknown device\n");
30469a391c7bSWingMan Kwok 		return -EINVAL;
30479a391c7bSWingMan Kwok 	}
30489a391c7bSWingMan Kwok 	gbe_dev->max_num_ports = gbe_dev->max_num_slaves + 1;
30499a391c7bSWingMan Kwok 
30506f8d3f33SWingman Kwok 	gbe_dev->dev = dev;
30516f8d3f33SWingman Kwok 	gbe_dev->netcp_device = netcp_device;
30526f8d3f33SWingman Kwok 	gbe_dev->rx_packet_max = NETCP_MAX_FRAME_SIZE;
30536f8d3f33SWingman Kwok 
30546f8d3f33SWingman Kwok 	/* init the hw stats lock */
30556f8d3f33SWingman Kwok 	spin_lock_init(&gbe_dev->hw_stats_lock);
30566f8d3f33SWingman Kwok 
30576f8d3f33SWingman Kwok 	if (of_find_property(node, "enable-ale", NULL)) {
30586f8d3f33SWingman Kwok 		gbe_dev->enable_ale = true;
30596f8d3f33SWingman Kwok 		dev_info(dev, "ALE enabled\n");
30606f8d3f33SWingman Kwok 	} else {
30616f8d3f33SWingman Kwok 		gbe_dev->enable_ale = false;
30626f8d3f33SWingman Kwok 		dev_dbg(dev, "ALE bypass enabled*\n");
30636f8d3f33SWingman Kwok 	}
30646f8d3f33SWingman Kwok 
30656f8d3f33SWingman Kwok 	ret = of_property_read_u32(node, "tx-queue",
30666f8d3f33SWingman Kwok 				   &gbe_dev->tx_queue_id);
30676f8d3f33SWingman Kwok 	if (ret < 0) {
30686f8d3f33SWingman Kwok 		dev_err(dev, "missing tx_queue parameter\n");
30696f8d3f33SWingman Kwok 		gbe_dev->tx_queue_id = GBE_TX_QUEUE;
30706f8d3f33SWingman Kwok 	}
30716f8d3f33SWingman Kwok 
30726f8d3f33SWingman Kwok 	ret = of_property_read_string(node, "tx-channel",
30736f8d3f33SWingman Kwok 				      &gbe_dev->dma_chan_name);
30746f8d3f33SWingman Kwok 	if (ret < 0) {
30756f8d3f33SWingman Kwok 		dev_err(dev, "missing \"tx-channel\" parameter\n");
30766f8d3f33SWingman Kwok 		ret = -ENODEV;
30776f8d3f33SWingman Kwok 		goto quit;
30786f8d3f33SWingman Kwok 	}
30796f8d3f33SWingman Kwok 
30806f8d3f33SWingman Kwok 	if (!strcmp(node->name, "gbe")) {
30816f8d3f33SWingman Kwok 		ret = get_gbe_resource_version(gbe_dev, node);
30826f8d3f33SWingman Kwok 		if (ret)
30836f8d3f33SWingman Kwok 			goto quit;
30846f8d3f33SWingman Kwok 
30859a391c7bSWingMan Kwok 		dev_dbg(dev, "ss_version: 0x%08x\n", gbe_dev->ss_version);
30869a391c7bSWingMan Kwok 
30879a391c7bSWingMan Kwok 		if (gbe_dev->ss_version == GBE_SS_VERSION_14)
30886f8d3f33SWingman Kwok 			ret = set_gbe_ethss14_priv(gbe_dev, node);
30899a391c7bSWingMan Kwok 		else if (IS_SS_ID_MU(gbe_dev))
30909a391c7bSWingMan Kwok 			ret = set_gbenu_ethss_priv(gbe_dev, node);
30919a391c7bSWingMan Kwok 		else
30929a391c7bSWingMan Kwok 			ret = -ENODEV;
30939a391c7bSWingMan Kwok 
30946f8d3f33SWingman Kwok 		if (ret)
30956f8d3f33SWingman Kwok 			goto quit;
309690cff9e2SWingman Kwok 	} else if (!strcmp(node->name, "xgbe")) {
309790cff9e2SWingman Kwok 		ret = set_xgbe_ethss10_priv(gbe_dev, node);
309890cff9e2SWingman Kwok 		if (ret)
309990cff9e2SWingman Kwok 			goto quit;
310090cff9e2SWingman Kwok 		ret = netcp_xgbe_serdes_init(gbe_dev->xgbe_serdes_regs,
310190cff9e2SWingman Kwok 					     gbe_dev->ss_regs);
310290cff9e2SWingman Kwok 		if (ret)
310390cff9e2SWingman Kwok 			goto quit;
31046f8d3f33SWingman Kwok 	} else {
31056f8d3f33SWingman Kwok 		dev_err(dev, "unknown GBE node(%s)\n", node->name);
31066f8d3f33SWingman Kwok 		ret = -ENODEV;
31076f8d3f33SWingman Kwok 		goto quit;
31086f8d3f33SWingman Kwok 	}
31096f8d3f33SWingman Kwok 
31106f8d3f33SWingman Kwok 	interfaces = of_get_child_by_name(node, "interfaces");
31116f8d3f33SWingman Kwok 	if (!interfaces)
31126f8d3f33SWingman Kwok 		dev_err(dev, "could not find interfaces\n");
31136f8d3f33SWingman Kwok 
31146f8d3f33SWingman Kwok 	ret = netcp_txpipe_init(&gbe_dev->tx_pipe, netcp_device,
31156f8d3f33SWingman Kwok 				gbe_dev->dma_chan_name, gbe_dev->tx_queue_id);
31166f8d3f33SWingman Kwok 	if (ret)
31176f8d3f33SWingman Kwok 		goto quit;
31186f8d3f33SWingman Kwok 
31196f8d3f33SWingman Kwok 	ret = netcp_txpipe_open(&gbe_dev->tx_pipe);
31206f8d3f33SWingman Kwok 	if (ret)
31216f8d3f33SWingman Kwok 		goto quit;
31226f8d3f33SWingman Kwok 
31236f8d3f33SWingman Kwok 	/* Create network interfaces */
31246f8d3f33SWingman Kwok 	INIT_LIST_HEAD(&gbe_dev->gbe_intf_head);
31256f8d3f33SWingman Kwok 	for_each_child_of_node(interfaces, interface) {
31266f8d3f33SWingman Kwok 		ret = of_property_read_u32(interface, "slave-port", &slave_num);
31276f8d3f33SWingman Kwok 		if (ret) {
31286f8d3f33SWingman Kwok 			dev_err(dev, "missing slave-port parameter, skipping interface configuration for %s\n",
31296f8d3f33SWingman Kwok 				interface->name);
31306f8d3f33SWingman Kwok 			continue;
31316f8d3f33SWingman Kwok 		}
31326f8d3f33SWingman Kwok 		gbe_dev->num_slaves++;
31339a391c7bSWingMan Kwok 		if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves)
31349a391c7bSWingMan Kwok 			break;
31356f8d3f33SWingman Kwok 	}
31366f8d3f33SWingman Kwok 
31376f8d3f33SWingman Kwok 	if (!gbe_dev->num_slaves)
31386f8d3f33SWingman Kwok 		dev_warn(dev, "No network interface configured\n");
31396f8d3f33SWingman Kwok 
31406f8d3f33SWingman Kwok 	/* Initialize Secondary slave ports */
31416f8d3f33SWingman Kwok 	secondary_ports = of_get_child_by_name(node, "secondary-slave-ports");
31426f8d3f33SWingman Kwok 	INIT_LIST_HEAD(&gbe_dev->secondary_slaves);
31439a391c7bSWingMan Kwok 	if (secondary_ports && (gbe_dev->num_slaves <  gbe_dev->max_num_slaves))
31446f8d3f33SWingman Kwok 		init_secondary_ports(gbe_dev, secondary_ports);
31456f8d3f33SWingman Kwok 	of_node_put(secondary_ports);
31466f8d3f33SWingman Kwok 
31476f8d3f33SWingman Kwok 	if (!gbe_dev->num_slaves) {
31486f8d3f33SWingman Kwok 		dev_err(dev, "No network interface or secondary ports configured\n");
31496f8d3f33SWingman Kwok 		ret = -ENODEV;
31506f8d3f33SWingman Kwok 		goto quit;
31516f8d3f33SWingman Kwok 	}
31526f8d3f33SWingman Kwok 
31536f8d3f33SWingman Kwok 	memset(&ale_params, 0, sizeof(ale_params));
31546f8d3f33SWingman Kwok 	ale_params.dev		= gbe_dev->dev;
31556f8d3f33SWingman Kwok 	ale_params.ale_regs	= gbe_dev->ale_reg;
31566f8d3f33SWingman Kwok 	ale_params.ale_ageout	= GBE_DEFAULT_ALE_AGEOUT;
31576f8d3f33SWingman Kwok 	ale_params.ale_entries	= gbe_dev->ale_entries;
31586f8d3f33SWingman Kwok 	ale_params.ale_ports	= gbe_dev->ale_ports;
31596f8d3f33SWingman Kwok 
31606f8d3f33SWingman Kwok 	gbe_dev->ale = cpsw_ale_create(&ale_params);
31616f8d3f33SWingman Kwok 	if (!gbe_dev->ale) {
31626f8d3f33SWingman Kwok 		dev_err(gbe_dev->dev, "error initializing ale engine\n");
31636f8d3f33SWingman Kwok 		ret = -ENODEV;
31646f8d3f33SWingman Kwok 		goto quit;
31656f8d3f33SWingman Kwok 	} else {
31666f8d3f33SWingman Kwok 		dev_dbg(gbe_dev->dev, "Created a gbe ale engine\n");
31676f8d3f33SWingman Kwok 	}
31686f8d3f33SWingman Kwok 
31696f8d3f33SWingman Kwok 	/* initialize host port */
31706f8d3f33SWingman Kwok 	gbe_init_host_port(gbe_dev);
31716f8d3f33SWingman Kwok 
3172489e8a2fSWingMan Kwok 	spin_lock_bh(&gbe_dev->hw_stats_lock);
3173489e8a2fSWingMan Kwok 	for (i = 0; i < gbe_dev->num_stats_mods; i++) {
3174489e8a2fSWingMan Kwok 		if (gbe_dev->ss_version == GBE_SS_VERSION_14)
3175489e8a2fSWingMan Kwok 			gbe_reset_mod_stats_ver14(gbe_dev, i);
3176489e8a2fSWingMan Kwok 		else
3177489e8a2fSWingMan Kwok 			gbe_reset_mod_stats(gbe_dev, i);
3178489e8a2fSWingMan Kwok 	}
3179489e8a2fSWingMan Kwok 	spin_unlock_bh(&gbe_dev->hw_stats_lock);
3180489e8a2fSWingMan Kwok 
31816f8d3f33SWingman Kwok 	init_timer(&gbe_dev->timer);
31826f8d3f33SWingman Kwok 	gbe_dev->timer.data	 = (unsigned long)gbe_dev;
31836f8d3f33SWingman Kwok 	gbe_dev->timer.function = netcp_ethss_timer;
31846f8d3f33SWingman Kwok 	gbe_dev->timer.expires	 = jiffies + GBE_TIMER_INTERVAL;
31856f8d3f33SWingman Kwok 	add_timer(&gbe_dev->timer);
31866f8d3f33SWingman Kwok 	*inst_priv = gbe_dev;
31876f8d3f33SWingman Kwok 	return 0;
31886f8d3f33SWingman Kwok 
31896f8d3f33SWingman Kwok quit:
31906f8d3f33SWingman Kwok 	if (gbe_dev->hw_stats)
31916f8d3f33SWingman Kwok 		devm_kfree(dev, gbe_dev->hw_stats);
3192489e8a2fSWingMan Kwok 	if (gbe_dev->hw_stats_prev)
3193489e8a2fSWingMan Kwok 		devm_kfree(dev, gbe_dev->hw_stats_prev);
31946f8d3f33SWingman Kwok 	cpsw_ale_destroy(gbe_dev->ale);
31956f8d3f33SWingman Kwok 	if (gbe_dev->ss_regs)
31966f8d3f33SWingman Kwok 		devm_iounmap(dev, gbe_dev->ss_regs);
31976f8d3f33SWingman Kwok 	of_node_put(interfaces);
31986f8d3f33SWingman Kwok 	devm_kfree(dev, gbe_dev);
31996f8d3f33SWingman Kwok 	return ret;
32006f8d3f33SWingman Kwok }
32016f8d3f33SWingman Kwok 
32026f8d3f33SWingman Kwok static int gbe_attach(void *inst_priv, struct net_device *ndev,
32036f8d3f33SWingman Kwok 		      struct device_node *node, void **intf_priv)
32046f8d3f33SWingman Kwok {
32056f8d3f33SWingman Kwok 	struct gbe_priv *gbe_dev = inst_priv;
32066f8d3f33SWingman Kwok 	struct gbe_intf *gbe_intf;
32076f8d3f33SWingman Kwok 	int ret;
32086f8d3f33SWingman Kwok 
32096f8d3f33SWingman Kwok 	if (!node) {
32106f8d3f33SWingman Kwok 		dev_err(gbe_dev->dev, "interface node not available\n");
32116f8d3f33SWingman Kwok 		return -ENODEV;
32126f8d3f33SWingman Kwok 	}
32136f8d3f33SWingman Kwok 
32146f8d3f33SWingman Kwok 	gbe_intf = devm_kzalloc(gbe_dev->dev, sizeof(*gbe_intf), GFP_KERNEL);
32156f8d3f33SWingman Kwok 	if (!gbe_intf)
32166f8d3f33SWingman Kwok 		return -ENOMEM;
32176f8d3f33SWingman Kwok 
32186f8d3f33SWingman Kwok 	gbe_intf->ndev = ndev;
32196f8d3f33SWingman Kwok 	gbe_intf->dev = gbe_dev->dev;
32206f8d3f33SWingman Kwok 	gbe_intf->gbe_dev = gbe_dev;
32216f8d3f33SWingman Kwok 
32226f8d3f33SWingman Kwok 	gbe_intf->slave = devm_kzalloc(gbe_dev->dev,
32236f8d3f33SWingman Kwok 					sizeof(*gbe_intf->slave),
32246f8d3f33SWingman Kwok 					GFP_KERNEL);
32256f8d3f33SWingman Kwok 	if (!gbe_intf->slave) {
32266f8d3f33SWingman Kwok 		ret = -ENOMEM;
32276f8d3f33SWingman Kwok 		goto fail;
32286f8d3f33SWingman Kwok 	}
32296f8d3f33SWingman Kwok 
32306f8d3f33SWingman Kwok 	if (init_slave(gbe_dev, gbe_intf->slave, node)) {
32316f8d3f33SWingman Kwok 		ret = -ENODEV;
32326f8d3f33SWingman Kwok 		goto fail;
32336f8d3f33SWingman Kwok 	}
32346f8d3f33SWingman Kwok 
32356f8d3f33SWingman Kwok 	gbe_intf->tx_pipe = gbe_dev->tx_pipe;
32366f8d3f33SWingman Kwok 	ndev->ethtool_ops = &keystone_ethtool_ops;
32376f8d3f33SWingman Kwok 	list_add_tail(&gbe_intf->gbe_intf_list, &gbe_dev->gbe_intf_head);
32386f8d3f33SWingman Kwok 	*intf_priv = gbe_intf;
32396f8d3f33SWingman Kwok 	return 0;
32406f8d3f33SWingman Kwok 
32416f8d3f33SWingman Kwok fail:
32426f8d3f33SWingman Kwok 	if (gbe_intf->slave)
32436f8d3f33SWingman Kwok 		devm_kfree(gbe_dev->dev, gbe_intf->slave);
32446f8d3f33SWingman Kwok 	if (gbe_intf)
32456f8d3f33SWingman Kwok 		devm_kfree(gbe_dev->dev, gbe_intf);
32466f8d3f33SWingman Kwok 	return ret;
32476f8d3f33SWingman Kwok }
32486f8d3f33SWingman Kwok 
32496f8d3f33SWingman Kwok static int gbe_release(void *intf_priv)
32506f8d3f33SWingman Kwok {
32516f8d3f33SWingman Kwok 	struct gbe_intf *gbe_intf = intf_priv;
32526f8d3f33SWingman Kwok 
32536f8d3f33SWingman Kwok 	gbe_intf->ndev->ethtool_ops = NULL;
32546f8d3f33SWingman Kwok 	list_del(&gbe_intf->gbe_intf_list);
32556f8d3f33SWingman Kwok 	devm_kfree(gbe_intf->dev, gbe_intf->slave);
32566f8d3f33SWingman Kwok 	devm_kfree(gbe_intf->dev, gbe_intf);
32576f8d3f33SWingman Kwok 	return 0;
32586f8d3f33SWingman Kwok }
32596f8d3f33SWingman Kwok 
32606f8d3f33SWingman Kwok static int gbe_remove(struct netcp_device *netcp_device, void *inst_priv)
32616f8d3f33SWingman Kwok {
32626f8d3f33SWingman Kwok 	struct gbe_priv *gbe_dev = inst_priv;
32636f8d3f33SWingman Kwok 
32646f8d3f33SWingman Kwok 	del_timer_sync(&gbe_dev->timer);
32656f8d3f33SWingman Kwok 	cpsw_ale_stop(gbe_dev->ale);
32666f8d3f33SWingman Kwok 	cpsw_ale_destroy(gbe_dev->ale);
32676f8d3f33SWingman Kwok 	netcp_txpipe_close(&gbe_dev->tx_pipe);
32686f8d3f33SWingman Kwok 	free_secondary_ports(gbe_dev);
32696f8d3f33SWingman Kwok 
32706f8d3f33SWingman Kwok 	if (!list_empty(&gbe_dev->gbe_intf_head))
32716f8d3f33SWingman Kwok 		dev_alert(gbe_dev->dev, "unreleased ethss interfaces present\n");
32726f8d3f33SWingman Kwok 
32736f8d3f33SWingman Kwok 	devm_kfree(gbe_dev->dev, gbe_dev->hw_stats);
32746f8d3f33SWingman Kwok 	devm_iounmap(gbe_dev->dev, gbe_dev->ss_regs);
32756f8d3f33SWingman Kwok 	memset(gbe_dev, 0x00, sizeof(*gbe_dev));
32766f8d3f33SWingman Kwok 	devm_kfree(gbe_dev->dev, gbe_dev);
32776f8d3f33SWingman Kwok 	return 0;
32786f8d3f33SWingman Kwok }
32796f8d3f33SWingman Kwok 
32806f8d3f33SWingman Kwok static struct netcp_module gbe_module = {
32816f8d3f33SWingman Kwok 	.name		= GBE_MODULE_NAME,
32826f8d3f33SWingman Kwok 	.owner		= THIS_MODULE,
32836f8d3f33SWingman Kwok 	.primary	= true,
32846f8d3f33SWingman Kwok 	.probe		= gbe_probe,
32856f8d3f33SWingman Kwok 	.open		= gbe_open,
32866f8d3f33SWingman Kwok 	.close		= gbe_close,
32876f8d3f33SWingman Kwok 	.remove		= gbe_remove,
32886f8d3f33SWingman Kwok 	.attach		= gbe_attach,
32896f8d3f33SWingman Kwok 	.release	= gbe_release,
32906f8d3f33SWingman Kwok 	.add_addr	= gbe_add_addr,
32916f8d3f33SWingman Kwok 	.del_addr	= gbe_del_addr,
32926f8d3f33SWingman Kwok 	.add_vid	= gbe_add_vid,
32936f8d3f33SWingman Kwok 	.del_vid	= gbe_del_vid,
32946f8d3f33SWingman Kwok 	.ioctl		= gbe_ioctl,
32956f8d3f33SWingman Kwok };
32966f8d3f33SWingman Kwok 
329790cff9e2SWingman Kwok static struct netcp_module xgbe_module = {
329890cff9e2SWingman Kwok 	.name		= XGBE_MODULE_NAME,
329990cff9e2SWingman Kwok 	.owner		= THIS_MODULE,
330090cff9e2SWingman Kwok 	.primary	= true,
330190cff9e2SWingman Kwok 	.probe		= gbe_probe,
330290cff9e2SWingman Kwok 	.open		= gbe_open,
330390cff9e2SWingman Kwok 	.close		= gbe_close,
330490cff9e2SWingman Kwok 	.remove		= gbe_remove,
330590cff9e2SWingman Kwok 	.attach		= gbe_attach,
330690cff9e2SWingman Kwok 	.release	= gbe_release,
330790cff9e2SWingman Kwok 	.add_addr	= gbe_add_addr,
330890cff9e2SWingman Kwok 	.del_addr	= gbe_del_addr,
330990cff9e2SWingman Kwok 	.add_vid	= gbe_add_vid,
331090cff9e2SWingman Kwok 	.del_vid	= gbe_del_vid,
331190cff9e2SWingman Kwok 	.ioctl		= gbe_ioctl,
331290cff9e2SWingman Kwok };
331390cff9e2SWingman Kwok 
33146f8d3f33SWingman Kwok static int __init keystone_gbe_init(void)
33156f8d3f33SWingman Kwok {
33166f8d3f33SWingman Kwok 	int ret;
33176f8d3f33SWingman Kwok 
33186f8d3f33SWingman Kwok 	ret = netcp_register_module(&gbe_module);
33196f8d3f33SWingman Kwok 	if (ret)
33206f8d3f33SWingman Kwok 		return ret;
33216f8d3f33SWingman Kwok 
332290cff9e2SWingman Kwok 	ret = netcp_register_module(&xgbe_module);
332390cff9e2SWingman Kwok 	if (ret)
332490cff9e2SWingman Kwok 		return ret;
332590cff9e2SWingman Kwok 
33266f8d3f33SWingman Kwok 	return 0;
33276f8d3f33SWingman Kwok }
33286f8d3f33SWingman Kwok module_init(keystone_gbe_init);
33296f8d3f33SWingman Kwok 
33306f8d3f33SWingman Kwok static void __exit keystone_gbe_exit(void)
33316f8d3f33SWingman Kwok {
33326f8d3f33SWingman Kwok 	netcp_unregister_module(&gbe_module);
333390cff9e2SWingman Kwok 	netcp_unregister_module(&xgbe_module);
33346f8d3f33SWingman Kwok }
33356f8d3f33SWingman Kwok module_exit(keystone_gbe_exit);
333658c11b5fSKaricheri, Muralidharan 
333758c11b5fSKaricheri, Muralidharan MODULE_LICENSE("GPL v2");
333858c11b5fSKaricheri, Muralidharan MODULE_DESCRIPTION("TI NETCP ETHSS driver for Keystone SOCs");
333958c11b5fSKaricheri, Muralidharan MODULE_AUTHOR("Sandeep Nair <sandeep_n@ti.com");
3340