xref: /dpdk/drivers/net/axgbe/axgbe_phy_impl.c (revision a3ec01b4e05c8f12462b7af824d2acda4fee3138)
14ac7516bSRavi Kumar /*   SPDX-License-Identifier: BSD-3-Clause
24ac7516bSRavi Kumar  *   Copyright(c) 2018 Advanced Micro Devices, Inc. All rights reserved.
34ac7516bSRavi Kumar  *   Copyright(c) 2018 Synopsys, Inc. All rights reserved.
44ac7516bSRavi Kumar  */
54ac7516bSRavi Kumar 
64ac7516bSRavi Kumar #include "axgbe_ethdev.h"
74ac7516bSRavi Kumar #include "axgbe_common.h"
84ac7516bSRavi Kumar #include "axgbe_phy.h"
94ac7516bSRavi Kumar 
10a935a4c3SSelwin Sebastian #define AXGBE_PHY_PORT_SPEED_100	BIT(1)
11a935a4c3SSelwin Sebastian #define AXGBE_PHY_PORT_SPEED_1000	BIT(2)
12a935a4c3SSelwin Sebastian #define AXGBE_PHY_PORT_SPEED_2500	BIT(3)
13a935a4c3SSelwin Sebastian #define AXGBE_PHY_PORT_SPEED_10000	BIT(4)
144ac7516bSRavi Kumar 
154ac7516bSRavi Kumar #define AXGBE_MUTEX_RELEASE		0x80000000
164ac7516bSRavi Kumar 
174ac7516bSRavi Kumar #define AXGBE_SFP_DIRECT		7
184ac7516bSRavi Kumar 
194ac7516bSRavi Kumar /* I2C target addresses */
204ac7516bSRavi Kumar #define AXGBE_SFP_SERIAL_ID_ADDRESS	0x50
214ac7516bSRavi Kumar #define AXGBE_SFP_DIAG_INFO_ADDRESS	0x51
224ac7516bSRavi Kumar #define AXGBE_SFP_PHY_ADDRESS		0x56
234ac7516bSRavi Kumar #define AXGBE_GPIO_ADDRESS_PCA9555	0x20
244ac7516bSRavi Kumar 
254ac7516bSRavi Kumar /* SFP sideband signal indicators */
264ac7516bSRavi Kumar #define AXGBE_GPIO_NO_TX_FAULT		BIT(0)
274ac7516bSRavi Kumar #define AXGBE_GPIO_NO_RATE_SELECT	BIT(1)
284ac7516bSRavi Kumar #define AXGBE_GPIO_NO_MOD_ABSENT	BIT(2)
294ac7516bSRavi Kumar #define AXGBE_GPIO_NO_RX_LOS		BIT(3)
304ac7516bSRavi Kumar 
314ac7516bSRavi Kumar /* Rate-change complete wait/retry count */
324ac7516bSRavi Kumar #define AXGBE_RATECHANGE_COUNT		500
334ac7516bSRavi Kumar 
3400072056SRavi Kumar /* CDR delay values for KR support (in usec) */
3500072056SRavi Kumar #define AXGBE_CDR_DELAY_INIT		10000
3600072056SRavi Kumar #define AXGBE_CDR_DELAY_INC		10000
3700072056SRavi Kumar #define AXGBE_CDR_DELAY_MAX		100000
3800072056SRavi Kumar 
394ac7516bSRavi Kumar enum axgbe_port_mode {
404ac7516bSRavi Kumar 	AXGBE_PORT_MODE_RSVD = 0,
414ac7516bSRavi Kumar 	AXGBE_PORT_MODE_BACKPLANE,
424ac7516bSRavi Kumar 	AXGBE_PORT_MODE_BACKPLANE_2500,
434ac7516bSRavi Kumar 	AXGBE_PORT_MODE_1000BASE_T,
444ac7516bSRavi Kumar 	AXGBE_PORT_MODE_1000BASE_X,
454ac7516bSRavi Kumar 	AXGBE_PORT_MODE_NBASE_T,
464ac7516bSRavi Kumar 	AXGBE_PORT_MODE_10GBASE_T,
474ac7516bSRavi Kumar 	AXGBE_PORT_MODE_10GBASE_R,
484ac7516bSRavi Kumar 	AXGBE_PORT_MODE_SFP,
49443ab5aaSSelwin Sebastian 	AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG,
504ac7516bSRavi Kumar 	AXGBE_PORT_MODE_MAX,
514ac7516bSRavi Kumar };
524ac7516bSRavi Kumar 
534ac7516bSRavi Kumar enum axgbe_conn_type {
544ac7516bSRavi Kumar 	AXGBE_CONN_TYPE_NONE = 0,
554ac7516bSRavi Kumar 	AXGBE_CONN_TYPE_SFP,
564ac7516bSRavi Kumar 	AXGBE_CONN_TYPE_MDIO,
574ac7516bSRavi Kumar 	AXGBE_CONN_TYPE_RSVD1,
584ac7516bSRavi Kumar 	AXGBE_CONN_TYPE_BACKPLANE,
594ac7516bSRavi Kumar 	AXGBE_CONN_TYPE_MAX,
604ac7516bSRavi Kumar };
614ac7516bSRavi Kumar 
624ac7516bSRavi Kumar /* SFP/SFP+ related definitions */
634ac7516bSRavi Kumar enum axgbe_sfp_comm {
644ac7516bSRavi Kumar 	AXGBE_SFP_COMM_DIRECT = 0,
654ac7516bSRavi Kumar 	AXGBE_SFP_COMM_PCA9545,
664ac7516bSRavi Kumar };
674ac7516bSRavi Kumar 
684ac7516bSRavi Kumar enum axgbe_sfp_cable {
694ac7516bSRavi Kumar 	AXGBE_SFP_CABLE_UNKNOWN = 0,
704ac7516bSRavi Kumar 	AXGBE_SFP_CABLE_ACTIVE,
714ac7516bSRavi Kumar 	AXGBE_SFP_CABLE_PASSIVE,
724ac7516bSRavi Kumar };
734ac7516bSRavi Kumar 
744ac7516bSRavi Kumar enum axgbe_sfp_base {
754ac7516bSRavi Kumar 	AXGBE_SFP_BASE_UNKNOWN = 0,
764ac7516bSRavi Kumar 	AXGBE_SFP_BASE_1000_T,
774ac7516bSRavi Kumar 	AXGBE_SFP_BASE_1000_SX,
784ac7516bSRavi Kumar 	AXGBE_SFP_BASE_1000_LX,
794ac7516bSRavi Kumar 	AXGBE_SFP_BASE_1000_CX,
804ac7516bSRavi Kumar 	AXGBE_SFP_BASE_10000_SR,
814ac7516bSRavi Kumar 	AXGBE_SFP_BASE_10000_LR,
824ac7516bSRavi Kumar 	AXGBE_SFP_BASE_10000_LRM,
834ac7516bSRavi Kumar 	AXGBE_SFP_BASE_10000_ER,
844ac7516bSRavi Kumar 	AXGBE_SFP_BASE_10000_CR,
854ac7516bSRavi Kumar };
864ac7516bSRavi Kumar 
874ac7516bSRavi Kumar enum axgbe_sfp_speed {
884ac7516bSRavi Kumar 	AXGBE_SFP_SPEED_UNKNOWN = 0,
894ac7516bSRavi Kumar 	AXGBE_SFP_SPEED_100_1000,
904ac7516bSRavi Kumar 	AXGBE_SFP_SPEED_1000,
914ac7516bSRavi Kumar 	AXGBE_SFP_SPEED_10000,
924ac7516bSRavi Kumar };
934ac7516bSRavi Kumar 
944ac7516bSRavi Kumar /* SFP Serial ID Base ID values relative to an offset of 0 */
954ac7516bSRavi Kumar #define AXGBE_SFP_BASE_ID			0
964ac7516bSRavi Kumar #define AXGBE_SFP_ID_SFP			0x03
974ac7516bSRavi Kumar 
984ac7516bSRavi Kumar #define AXGBE_SFP_BASE_EXT_ID			1
994ac7516bSRavi Kumar #define AXGBE_SFP_EXT_ID_SFP			0x04
1004ac7516bSRavi Kumar 
1014ac7516bSRavi Kumar #define AXGBE_SFP_BASE_10GBE_CC			3
1024ac7516bSRavi Kumar #define AXGBE_SFP_BASE_10GBE_CC_SR		BIT(4)
1034ac7516bSRavi Kumar #define AXGBE_SFP_BASE_10GBE_CC_LR		BIT(5)
1044ac7516bSRavi Kumar #define AXGBE_SFP_BASE_10GBE_CC_LRM		BIT(6)
1054ac7516bSRavi Kumar #define AXGBE_SFP_BASE_10GBE_CC_ER		BIT(7)
1064ac7516bSRavi Kumar 
1074ac7516bSRavi Kumar #define AXGBE_SFP_BASE_1GBE_CC			6
1084ac7516bSRavi Kumar #define AXGBE_SFP_BASE_1GBE_CC_SX		BIT(0)
1094ac7516bSRavi Kumar #define AXGBE_SFP_BASE_1GBE_CC_LX		BIT(1)
1104ac7516bSRavi Kumar #define AXGBE_SFP_BASE_1GBE_CC_CX		BIT(2)
1114ac7516bSRavi Kumar #define AXGBE_SFP_BASE_1GBE_CC_T		BIT(3)
1124ac7516bSRavi Kumar 
1134ac7516bSRavi Kumar #define AXGBE_SFP_BASE_CABLE			8
1144ac7516bSRavi Kumar #define AXGBE_SFP_BASE_CABLE_PASSIVE		BIT(2)
1154ac7516bSRavi Kumar #define AXGBE_SFP_BASE_CABLE_ACTIVE		BIT(3)
1164ac7516bSRavi Kumar 
1174ac7516bSRavi Kumar #define AXGBE_SFP_BASE_BR			12
1184ac7516bSRavi Kumar #define AXGBE_SFP_BASE_BR_1GBE_MIN		0x0a
1194ac7516bSRavi Kumar #define AXGBE_SFP_BASE_BR_1GBE_MAX		0x0d
1204ac7516bSRavi Kumar #define AXGBE_SFP_BASE_BR_10GBE_MIN		0x64
1214ac7516bSRavi Kumar #define AXGBE_SFP_BASE_BR_10GBE_MAX		0x68
1224ac7516bSRavi Kumar 
1234ac7516bSRavi Kumar #define AXGBE_SFP_BASE_CU_CABLE_LEN		18
1244ac7516bSRavi Kumar 
1254ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_NAME		20
1264ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_NAME_LEN		16
1274ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_PN		40
1284ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_PN_LEN		16
1294ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_REV		56
1304ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_REV_LEN		4
1314ac7516bSRavi Kumar 
1324ac7516bSRavi Kumar #define AXGBE_SFP_BASE_CC			63
1334ac7516bSRavi Kumar 
1344ac7516bSRavi Kumar /* SFP Serial ID Extended ID values relative to an offset of 64 */
1354ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_SN		4
1364ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_SN_LEN		16
1374ac7516bSRavi Kumar 
1384ac7516bSRavi Kumar #define AXGBE_SFP_EXTD_DIAG			28
1394ac7516bSRavi Kumar #define AXGBE_SFP_EXTD_DIAG_ADDR_CHANGE		BIT(2)
1404ac7516bSRavi Kumar 
1414ac7516bSRavi Kumar #define AXGBE_SFP_EXTD_SFF_8472			30
1424ac7516bSRavi Kumar 
1434ac7516bSRavi Kumar #define AXGBE_SFP_EXTD_CC			31
1444ac7516bSRavi Kumar 
1454ac7516bSRavi Kumar struct axgbe_sfp_eeprom {
1464ac7516bSRavi Kumar 	u8 base[64];
1474ac7516bSRavi Kumar 	u8 extd[32];
1484ac7516bSRavi Kumar 	u8 vendor[32];
1494ac7516bSRavi Kumar };
1504ac7516bSRavi Kumar 
1514ac7516bSRavi Kumar #define AXGBE_BEL_FUSE_VENDOR	"BEL-FUSE"
1524ac7516bSRavi Kumar #define AXGBE_BEL_FUSE_PARTNO	"1GBT-SFP06"
1534ac7516bSRavi Kumar 
1544ac7516bSRavi Kumar struct axgbe_sfp_ascii {
1554ac7516bSRavi Kumar 	union {
1564ac7516bSRavi Kumar 		char vendor[AXGBE_SFP_BASE_VENDOR_NAME_LEN + 1];
1574ac7516bSRavi Kumar 		char partno[AXGBE_SFP_BASE_VENDOR_PN_LEN + 1];
1584ac7516bSRavi Kumar 		char rev[AXGBE_SFP_BASE_VENDOR_REV_LEN + 1];
1594ac7516bSRavi Kumar 		char serno[AXGBE_SFP_BASE_VENDOR_SN_LEN + 1];
1604ac7516bSRavi Kumar 	} u;
1614ac7516bSRavi Kumar };
1624ac7516bSRavi Kumar 
1634ac7516bSRavi Kumar /* MDIO PHY reset types */
1644ac7516bSRavi Kumar enum axgbe_mdio_reset {
1654ac7516bSRavi Kumar 	AXGBE_MDIO_RESET_NONE = 0,
1664ac7516bSRavi Kumar 	AXGBE_MDIO_RESET_I2C_GPIO,
1674ac7516bSRavi Kumar 	AXGBE_MDIO_RESET_INT_GPIO,
1684ac7516bSRavi Kumar 	AXGBE_MDIO_RESET_MAX,
1694ac7516bSRavi Kumar };
1704ac7516bSRavi Kumar 
1714ac7516bSRavi Kumar /* Re-driver related definitions */
1724ac7516bSRavi Kumar enum axgbe_phy_redrv_if {
1734ac7516bSRavi Kumar 	AXGBE_PHY_REDRV_IF_MDIO = 0,
1744ac7516bSRavi Kumar 	AXGBE_PHY_REDRV_IF_I2C,
1754ac7516bSRavi Kumar 	AXGBE_PHY_REDRV_IF_MAX,
1764ac7516bSRavi Kumar };
1774ac7516bSRavi Kumar 
1784ac7516bSRavi Kumar enum axgbe_phy_redrv_model {
1794ac7516bSRavi Kumar 	AXGBE_PHY_REDRV_MODEL_4223 = 0,
1804ac7516bSRavi Kumar 	AXGBE_PHY_REDRV_MODEL_4227,
1814ac7516bSRavi Kumar 	AXGBE_PHY_REDRV_MODEL_MAX,
1824ac7516bSRavi Kumar };
1834ac7516bSRavi Kumar 
1844ac7516bSRavi Kumar enum axgbe_phy_redrv_mode {
1854ac7516bSRavi Kumar 	AXGBE_PHY_REDRV_MODE_CX = 5,
1864ac7516bSRavi Kumar 	AXGBE_PHY_REDRV_MODE_SR = 9,
1874ac7516bSRavi Kumar };
1884ac7516bSRavi Kumar 
1894ac7516bSRavi Kumar #define AXGBE_PHY_REDRV_MODE_REG	0x12b0
1904ac7516bSRavi Kumar 
1914ac7516bSRavi Kumar /* PHY related configuration information */
1924ac7516bSRavi Kumar struct axgbe_phy_data {
1934ac7516bSRavi Kumar 	enum axgbe_port_mode port_mode;
1944ac7516bSRavi Kumar 
1954ac7516bSRavi Kumar 	unsigned int port_id;
1964ac7516bSRavi Kumar 
1974ac7516bSRavi Kumar 	unsigned int port_speeds;
1984ac7516bSRavi Kumar 
1994ac7516bSRavi Kumar 	enum axgbe_conn_type conn_type;
2004ac7516bSRavi Kumar 
2014ac7516bSRavi Kumar 	enum axgbe_mode cur_mode;
2024ac7516bSRavi Kumar 	enum axgbe_mode start_mode;
2034ac7516bSRavi Kumar 
2044ac7516bSRavi Kumar 	unsigned int rrc_count;
2054ac7516bSRavi Kumar 
2064ac7516bSRavi Kumar 	unsigned int mdio_addr;
2074ac7516bSRavi Kumar 
2084ac7516bSRavi Kumar 	unsigned int comm_owned;
2094ac7516bSRavi Kumar 
2104ac7516bSRavi Kumar 	/* SFP Support */
2114ac7516bSRavi Kumar 	enum axgbe_sfp_comm sfp_comm;
2124ac7516bSRavi Kumar 	unsigned int sfp_mux_address;
2134ac7516bSRavi Kumar 	unsigned int sfp_mux_channel;
2144ac7516bSRavi Kumar 
2154ac7516bSRavi Kumar 	unsigned int sfp_gpio_address;
2164ac7516bSRavi Kumar 	unsigned int sfp_gpio_mask;
2174ac7516bSRavi Kumar 	unsigned int sfp_gpio_rx_los;
2184ac7516bSRavi Kumar 	unsigned int sfp_gpio_tx_fault;
2194ac7516bSRavi Kumar 	unsigned int sfp_gpio_mod_absent;
2204ac7516bSRavi Kumar 	unsigned int sfp_gpio_rate_select;
2214ac7516bSRavi Kumar 
2224ac7516bSRavi Kumar 	unsigned int sfp_rx_los;
2234ac7516bSRavi Kumar 	unsigned int sfp_tx_fault;
2244ac7516bSRavi Kumar 	unsigned int sfp_mod_absent;
2254ac7516bSRavi Kumar 	unsigned int sfp_diags;
2264ac7516bSRavi Kumar 	unsigned int sfp_changed;
2274ac7516bSRavi Kumar 	unsigned int sfp_phy_avail;
2284ac7516bSRavi Kumar 	unsigned int sfp_cable_len;
2294ac7516bSRavi Kumar 	enum axgbe_sfp_base sfp_base;
2304ac7516bSRavi Kumar 	enum axgbe_sfp_cable sfp_cable;
2314ac7516bSRavi Kumar 	enum axgbe_sfp_speed sfp_speed;
2324ac7516bSRavi Kumar 	struct axgbe_sfp_eeprom sfp_eeprom;
2334ac7516bSRavi Kumar 
2344ac7516bSRavi Kumar 	/* External PHY support */
2354ac7516bSRavi Kumar 	enum axgbe_mdio_mode phydev_mode;
2364ac7516bSRavi Kumar 	enum axgbe_mdio_reset mdio_reset;
2374ac7516bSRavi Kumar 	unsigned int mdio_reset_addr;
2384ac7516bSRavi Kumar 	unsigned int mdio_reset_gpio;
2394ac7516bSRavi Kumar 
2404ac7516bSRavi Kumar 	/* Re-driver support */
2414ac7516bSRavi Kumar 	unsigned int redrv;
2424ac7516bSRavi Kumar 	unsigned int redrv_if;
2434ac7516bSRavi Kumar 	unsigned int redrv_addr;
2444ac7516bSRavi Kumar 	unsigned int redrv_lane;
2454ac7516bSRavi Kumar 	unsigned int redrv_model;
24600072056SRavi Kumar 
24700072056SRavi Kumar 	/* KR AN support */
24800072056SRavi Kumar 	unsigned int phy_cdr_notrack;
24900072056SRavi Kumar 	unsigned int phy_cdr_delay;
2504ac7516bSRavi Kumar };
2514ac7516bSRavi Kumar 
252a5c72737SRavi Kumar static enum axgbe_an_mode axgbe_phy_an_mode(struct axgbe_port *pdata);
253a5c72737SRavi Kumar 
254a5c72737SRavi Kumar static int axgbe_phy_i2c_xfer(struct axgbe_port *pdata,
255a5c72737SRavi Kumar 			      struct axgbe_i2c_op *i2c_op)
256a5c72737SRavi Kumar {
257a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
258a5c72737SRavi Kumar 
259a5c72737SRavi Kumar 	/* Be sure we own the bus */
260a5c72737SRavi Kumar 	if (!phy_data->comm_owned)
261a5c72737SRavi Kumar 		return -EIO;
262a5c72737SRavi Kumar 
263a5c72737SRavi Kumar 	return pdata->i2c_if.i2c_xfer(pdata, i2c_op);
264a5c72737SRavi Kumar }
265a5c72737SRavi Kumar 
266a5c72737SRavi Kumar static int axgbe_phy_redrv_write(struct axgbe_port *pdata, unsigned int reg,
267a5c72737SRavi Kumar 				 unsigned int val)
268a5c72737SRavi Kumar {
269a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
270a5c72737SRavi Kumar 	struct axgbe_i2c_op i2c_op;
271a5c72737SRavi Kumar 	uint16_t *redrv_val;
272a5c72737SRavi Kumar 	u8 redrv_data[5], csum;
273a5c72737SRavi Kumar 	unsigned int i, retry;
274a5c72737SRavi Kumar 	int ret;
275a5c72737SRavi Kumar 
276a5c72737SRavi Kumar 	/* High byte of register contains read/write indicator */
277a5c72737SRavi Kumar 	redrv_data[0] = ((reg >> 8) & 0xff) << 1;
278a5c72737SRavi Kumar 	redrv_data[1] = reg & 0xff;
279a5c72737SRavi Kumar 	redrv_val = (uint16_t *)&redrv_data[2];
280a5c72737SRavi Kumar 	*redrv_val = rte_cpu_to_be_16(val);
281a5c72737SRavi Kumar 
282a5c72737SRavi Kumar 	/* Calculate 1 byte checksum */
283a5c72737SRavi Kumar 	csum = 0;
284a5c72737SRavi Kumar 	for (i = 0; i < 4; i++) {
285a5c72737SRavi Kumar 		csum += redrv_data[i];
286a5c72737SRavi Kumar 		if (redrv_data[i] > csum)
287a5c72737SRavi Kumar 			csum++;
288a5c72737SRavi Kumar 	}
289a5c72737SRavi Kumar 	redrv_data[4] = ~csum;
290a5c72737SRavi Kumar 
291a5c72737SRavi Kumar 	retry = 1;
292a5c72737SRavi Kumar again1:
293a5c72737SRavi Kumar 	i2c_op.cmd = AXGBE_I2C_CMD_WRITE;
294a5c72737SRavi Kumar 	i2c_op.target = phy_data->redrv_addr;
295a5c72737SRavi Kumar 	i2c_op.len = sizeof(redrv_data);
296a5c72737SRavi Kumar 	i2c_op.buf = redrv_data;
297a5c72737SRavi Kumar 	ret = axgbe_phy_i2c_xfer(pdata, &i2c_op);
298a5c72737SRavi Kumar 	if (ret) {
299a5c72737SRavi Kumar 		if ((ret == -EAGAIN) && retry--)
300a5c72737SRavi Kumar 			goto again1;
301a5c72737SRavi Kumar 
302a5c72737SRavi Kumar 		return ret;
303a5c72737SRavi Kumar 	}
304a5c72737SRavi Kumar 
305a5c72737SRavi Kumar 	retry = 1;
306a5c72737SRavi Kumar again2:
307a5c72737SRavi Kumar 	i2c_op.cmd = AXGBE_I2C_CMD_READ;
308a5c72737SRavi Kumar 	i2c_op.target = phy_data->redrv_addr;
309a5c72737SRavi Kumar 	i2c_op.len = 1;
310a5c72737SRavi Kumar 	i2c_op.buf = redrv_data;
311a5c72737SRavi Kumar 	ret = axgbe_phy_i2c_xfer(pdata, &i2c_op);
312a5c72737SRavi Kumar 	if (ret) {
313a5c72737SRavi Kumar 		if ((ret == -EAGAIN) && retry--)
314a5c72737SRavi Kumar 			goto again2;
315a5c72737SRavi Kumar 
316a5c72737SRavi Kumar 		return ret;
317a5c72737SRavi Kumar 	}
318a5c72737SRavi Kumar 
319a5c72737SRavi Kumar 	if (redrv_data[0] != 0xff) {
320a5c72737SRavi Kumar 		PMD_DRV_LOG(ERR, "Redriver write checksum error\n");
321a5c72737SRavi Kumar 		ret = -EIO;
322a5c72737SRavi Kumar 	}
323a5c72737SRavi Kumar 
324a5c72737SRavi Kumar 	return ret;
325a5c72737SRavi Kumar }
326a5c72737SRavi Kumar 
327a5c72737SRavi Kumar static int axgbe_phy_i2c_read(struct axgbe_port *pdata, unsigned int target,
328a5c72737SRavi Kumar 			      void *reg, unsigned int reg_len,
329a5c72737SRavi Kumar 			      void *val, unsigned int val_len)
330a5c72737SRavi Kumar {
331a5c72737SRavi Kumar 	struct axgbe_i2c_op i2c_op;
332a5c72737SRavi Kumar 	int retry, ret;
333a5c72737SRavi Kumar 
334a5c72737SRavi Kumar 	retry = 1;
335a5c72737SRavi Kumar again1:
336a5c72737SRavi Kumar 	/* Set the specified register to read */
337a5c72737SRavi Kumar 	i2c_op.cmd = AXGBE_I2C_CMD_WRITE;
338a5c72737SRavi Kumar 	i2c_op.target = target;
339a5c72737SRavi Kumar 	i2c_op.len = reg_len;
340a5c72737SRavi Kumar 	i2c_op.buf = reg;
341a5c72737SRavi Kumar 	ret = axgbe_phy_i2c_xfer(pdata, &i2c_op);
342a5c72737SRavi Kumar 	if (ret) {
343a5c72737SRavi Kumar 		if ((ret == -EAGAIN) && retry--)
344a5c72737SRavi Kumar 			goto again1;
345a5c72737SRavi Kumar 
346a5c72737SRavi Kumar 		return ret;
347a5c72737SRavi Kumar 	}
348a5c72737SRavi Kumar 
349a5c72737SRavi Kumar 	retry = 1;
350a5c72737SRavi Kumar again2:
3517be78d02SJosh Soref 	/* Read the specified register */
352a5c72737SRavi Kumar 	i2c_op.cmd = AXGBE_I2C_CMD_READ;
353a5c72737SRavi Kumar 	i2c_op.target = target;
354a5c72737SRavi Kumar 	i2c_op.len = val_len;
355a5c72737SRavi Kumar 	i2c_op.buf = val;
356a5c72737SRavi Kumar 	ret = axgbe_phy_i2c_xfer(pdata, &i2c_op);
357a5c72737SRavi Kumar 	if ((ret == -EAGAIN) && retry--)
358a5c72737SRavi Kumar 		goto again2;
359a5c72737SRavi Kumar 
360a5c72737SRavi Kumar 	return ret;
361a5c72737SRavi Kumar }
362a5c72737SRavi Kumar 
363a5c72737SRavi Kumar static int axgbe_phy_sfp_put_mux(struct axgbe_port *pdata)
364a5c72737SRavi Kumar {
365a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
366a5c72737SRavi Kumar 	struct axgbe_i2c_op i2c_op;
367a5c72737SRavi Kumar 	uint8_t mux_channel;
368a5c72737SRavi Kumar 
369a5c72737SRavi Kumar 	if (phy_data->sfp_comm == AXGBE_SFP_COMM_DIRECT)
370a5c72737SRavi Kumar 		return 0;
371a5c72737SRavi Kumar 
372a5c72737SRavi Kumar 	/* Select no mux channels */
373a5c72737SRavi Kumar 	mux_channel = 0;
374a5c72737SRavi Kumar 	i2c_op.cmd = AXGBE_I2C_CMD_WRITE;
375a5c72737SRavi Kumar 	i2c_op.target = phy_data->sfp_mux_address;
376a5c72737SRavi Kumar 	i2c_op.len = sizeof(mux_channel);
377a5c72737SRavi Kumar 	i2c_op.buf = &mux_channel;
378a5c72737SRavi Kumar 
379a5c72737SRavi Kumar 	return axgbe_phy_i2c_xfer(pdata, &i2c_op);
380a5c72737SRavi Kumar }
381a5c72737SRavi Kumar 
382a5c72737SRavi Kumar static int axgbe_phy_sfp_get_mux(struct axgbe_port *pdata)
383a5c72737SRavi Kumar {
384a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
385a5c72737SRavi Kumar 	struct axgbe_i2c_op i2c_op;
386a5c72737SRavi Kumar 	u8 mux_channel;
387a5c72737SRavi Kumar 
388a5c72737SRavi Kumar 	if (phy_data->sfp_comm == AXGBE_SFP_COMM_DIRECT)
389a5c72737SRavi Kumar 		return 0;
390a5c72737SRavi Kumar 
391a5c72737SRavi Kumar 	/* Select desired mux channel */
392a5c72737SRavi Kumar 	mux_channel = 1 << phy_data->sfp_mux_channel;
393a5c72737SRavi Kumar 	i2c_op.cmd = AXGBE_I2C_CMD_WRITE;
394a5c72737SRavi Kumar 	i2c_op.target = phy_data->sfp_mux_address;
395a5c72737SRavi Kumar 	i2c_op.len = sizeof(mux_channel);
396a5c72737SRavi Kumar 	i2c_op.buf = &mux_channel;
397a5c72737SRavi Kumar 
398a5c72737SRavi Kumar 	return axgbe_phy_i2c_xfer(pdata, &i2c_op);
399a5c72737SRavi Kumar }
400a5c72737SRavi Kumar 
401a5c72737SRavi Kumar static void axgbe_phy_put_comm_ownership(struct axgbe_port *pdata)
402a5c72737SRavi Kumar {
403a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
404a5c72737SRavi Kumar 
405a5c72737SRavi Kumar 	phy_data->comm_owned = 0;
406a5c72737SRavi Kumar 
407a5c72737SRavi Kumar 	pthread_mutex_unlock(&pdata->phy_mutex);
408a5c72737SRavi Kumar }
409a5c72737SRavi Kumar 
410a5c72737SRavi Kumar static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
411a5c72737SRavi Kumar {
412a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
413a5c72737SRavi Kumar 	uint64_t timeout;
414a5c72737SRavi Kumar 	unsigned int mutex_id;
415a5c72737SRavi Kumar 
416a5c72737SRavi Kumar 	/* The I2C and MDIO/GPIO bus is multiplexed between multiple devices,
417a5c72737SRavi Kumar 	 * the driver needs to take the software mutex and then the hardware
418a5c72737SRavi Kumar 	 * mutexes before being able to use the busses.
419a5c72737SRavi Kumar 	 */
420a5c72737SRavi Kumar 	pthread_mutex_lock(&pdata->phy_mutex);
421a5c72737SRavi Kumar 
422c8c2296bSPallantla Poornima 	if (phy_data->comm_owned)
423c8c2296bSPallantla Poornima 		return 0;
424c8c2296bSPallantla Poornima 
425a5c72737SRavi Kumar 	/* Clear the mutexes */
426a5c72737SRavi Kumar 	XP_IOWRITE(pdata, XP_I2C_MUTEX, AXGBE_MUTEX_RELEASE);
427a5c72737SRavi Kumar 	XP_IOWRITE(pdata, XP_MDIO_MUTEX, AXGBE_MUTEX_RELEASE);
428a5c72737SRavi Kumar 
429a5c72737SRavi Kumar 	/* Mutex formats are the same for I2C and MDIO/GPIO */
430a5c72737SRavi Kumar 	mutex_id = 0;
431a5c72737SRavi Kumar 	XP_SET_BITS(mutex_id, XP_I2C_MUTEX, ID, phy_data->port_id);
432a5c72737SRavi Kumar 	XP_SET_BITS(mutex_id, XP_I2C_MUTEX, ACTIVE, 1);
433a5c72737SRavi Kumar 
434a5c72737SRavi Kumar 	timeout = rte_get_timer_cycles() + (rte_get_timer_hz() * 5);
435a5c72737SRavi Kumar 	while (time_before(rte_get_timer_cycles(), timeout)) {
436a5c72737SRavi Kumar 		/* Must be all zeroes in order to obtain the mutex */
437a5c72737SRavi Kumar 		if (XP_IOREAD(pdata, XP_I2C_MUTEX) ||
438a5c72737SRavi Kumar 		    XP_IOREAD(pdata, XP_MDIO_MUTEX)) {
439a5c72737SRavi Kumar 			rte_delay_us(100);
440a5c72737SRavi Kumar 			continue;
441a5c72737SRavi Kumar 		}
442a5c72737SRavi Kumar 
443a5c72737SRavi Kumar 		/* Obtain the mutex */
444a5c72737SRavi Kumar 		XP_IOWRITE(pdata, XP_I2C_MUTEX, mutex_id);
445a5c72737SRavi Kumar 		XP_IOWRITE(pdata, XP_MDIO_MUTEX, mutex_id);
446a5c72737SRavi Kumar 
447a5c72737SRavi Kumar 		phy_data->comm_owned = 1;
448a5c72737SRavi Kumar 		return 0;
449a5c72737SRavi Kumar 	}
450a5c72737SRavi Kumar 
451a5c72737SRavi Kumar 	pthread_mutex_unlock(&pdata->phy_mutex);
452a5c72737SRavi Kumar 
453a5c72737SRavi Kumar 	PMD_DRV_LOG(ERR, "unable to obtain hardware mutexes\n");
454a5c72737SRavi Kumar 
455a5c72737SRavi Kumar 	return -ETIMEDOUT;
456a5c72737SRavi Kumar }
457a5c72737SRavi Kumar 
458a5c72737SRavi Kumar static void axgbe_phy_sfp_phy_settings(struct axgbe_port *pdata)
459a5c72737SRavi Kumar {
460a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
461a5c72737SRavi Kumar 
462a5c72737SRavi Kumar 	if (phy_data->sfp_mod_absent) {
463a5c72737SRavi Kumar 		pdata->phy.speed = SPEED_UNKNOWN;
464a5c72737SRavi Kumar 		pdata->phy.duplex = DUPLEX_UNKNOWN;
465a5c72737SRavi Kumar 		pdata->phy.autoneg = AUTONEG_ENABLE;
466a5c72737SRavi Kumar 		pdata->phy.advertising = pdata->phy.supported;
467a5c72737SRavi Kumar 	}
468a5c72737SRavi Kumar 
469a5c72737SRavi Kumar 	pdata->phy.advertising &= ~ADVERTISED_Autoneg;
470a5c72737SRavi Kumar 	pdata->phy.advertising &= ~ADVERTISED_TP;
471a5c72737SRavi Kumar 	pdata->phy.advertising &= ~ADVERTISED_FIBRE;
472a5c72737SRavi Kumar 	pdata->phy.advertising &= ~ADVERTISED_100baseT_Full;
473a5c72737SRavi Kumar 	pdata->phy.advertising &= ~ADVERTISED_1000baseT_Full;
474a5c72737SRavi Kumar 	pdata->phy.advertising &= ~ADVERTISED_10000baseT_Full;
475a5c72737SRavi Kumar 	pdata->phy.advertising &= ~ADVERTISED_10000baseR_FEC;
476a5c72737SRavi Kumar 
477a5c72737SRavi Kumar 	switch (phy_data->sfp_base) {
478a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_T:
479a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_SX:
480a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_LX:
481a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_CX:
482a5c72737SRavi Kumar 		pdata->phy.speed = SPEED_UNKNOWN;
483a5c72737SRavi Kumar 		pdata->phy.duplex = DUPLEX_UNKNOWN;
484a5c72737SRavi Kumar 		pdata->phy.autoneg = AUTONEG_ENABLE;
485a5c72737SRavi Kumar 		pdata->phy.advertising |= ADVERTISED_Autoneg;
486a5c72737SRavi Kumar 		break;
487a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_SR:
488a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_LR:
489a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_LRM:
490a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_ER:
491a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_CR:
492a5c72737SRavi Kumar 	default:
493a5c72737SRavi Kumar 		pdata->phy.speed = SPEED_10000;
494a5c72737SRavi Kumar 		pdata->phy.duplex = DUPLEX_FULL;
495a5c72737SRavi Kumar 		pdata->phy.autoneg = AUTONEG_DISABLE;
496a5c72737SRavi Kumar 		break;
497a5c72737SRavi Kumar 	}
498a5c72737SRavi Kumar 
499a5c72737SRavi Kumar 	switch (phy_data->sfp_base) {
500a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_T:
501a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_CX:
502a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_CR:
503a5c72737SRavi Kumar 		pdata->phy.advertising |= ADVERTISED_TP;
504a5c72737SRavi Kumar 		break;
505a5c72737SRavi Kumar 	default:
506a5c72737SRavi Kumar 		pdata->phy.advertising |= ADVERTISED_FIBRE;
507a5c72737SRavi Kumar 	}
508a5c72737SRavi Kumar 
509a5c72737SRavi Kumar 	switch (phy_data->sfp_speed) {
510a5c72737SRavi Kumar 	case AXGBE_SFP_SPEED_100_1000:
511a5c72737SRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100)
512a5c72737SRavi Kumar 			pdata->phy.advertising |= ADVERTISED_100baseT_Full;
513a5c72737SRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000)
514a5c72737SRavi Kumar 			pdata->phy.advertising |= ADVERTISED_1000baseT_Full;
515a5c72737SRavi Kumar 		break;
516a5c72737SRavi Kumar 	case AXGBE_SFP_SPEED_1000:
517a5c72737SRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000)
518a5c72737SRavi Kumar 			pdata->phy.advertising |= ADVERTISED_1000baseT_Full;
519a5c72737SRavi Kumar 		break;
520a5c72737SRavi Kumar 	case AXGBE_SFP_SPEED_10000:
521a5c72737SRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000)
522a5c72737SRavi Kumar 			pdata->phy.advertising |= ADVERTISED_10000baseT_Full;
523a5c72737SRavi Kumar 		break;
524a5c72737SRavi Kumar 	default:
525a5c72737SRavi Kumar 		/* Choose the fastest supported speed */
526a5c72737SRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000)
527a5c72737SRavi Kumar 			pdata->phy.advertising |= ADVERTISED_10000baseT_Full;
528a5c72737SRavi Kumar 		else if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000)
529a5c72737SRavi Kumar 			pdata->phy.advertising |= ADVERTISED_1000baseT_Full;
530a5c72737SRavi Kumar 		else if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100)
531a5c72737SRavi Kumar 			pdata->phy.advertising |= ADVERTISED_100baseT_Full;
532a5c72737SRavi Kumar 	}
533a5c72737SRavi Kumar }
534a5c72737SRavi Kumar 
535a5c72737SRavi Kumar static bool axgbe_phy_sfp_bit_rate(struct axgbe_sfp_eeprom *sfp_eeprom,
536a5c72737SRavi Kumar 				   enum axgbe_sfp_speed sfp_speed)
537a5c72737SRavi Kumar {
538a5c72737SRavi Kumar 	u8 *sfp_base, min, max;
539a5c72737SRavi Kumar 
540a5c72737SRavi Kumar 	sfp_base = sfp_eeprom->base;
541a5c72737SRavi Kumar 
542a5c72737SRavi Kumar 	switch (sfp_speed) {
543a5c72737SRavi Kumar 	case AXGBE_SFP_SPEED_1000:
544a5c72737SRavi Kumar 		min = AXGBE_SFP_BASE_BR_1GBE_MIN;
545a5c72737SRavi Kumar 		max = AXGBE_SFP_BASE_BR_1GBE_MAX;
546a5c72737SRavi Kumar 		break;
547a5c72737SRavi Kumar 	case AXGBE_SFP_SPEED_10000:
548a5c72737SRavi Kumar 		min = AXGBE_SFP_BASE_BR_10GBE_MIN;
549a5c72737SRavi Kumar 		max = AXGBE_SFP_BASE_BR_10GBE_MAX;
550a5c72737SRavi Kumar 		break;
551a5c72737SRavi Kumar 	default:
552a5c72737SRavi Kumar 		return false;
553a5c72737SRavi Kumar 	}
554a5c72737SRavi Kumar 
555a5c72737SRavi Kumar 	return ((sfp_base[AXGBE_SFP_BASE_BR] >= min) &&
556a5c72737SRavi Kumar 		(sfp_base[AXGBE_SFP_BASE_BR] <= max));
557a5c72737SRavi Kumar }
558a5c72737SRavi Kumar 
559a5c72737SRavi Kumar static void axgbe_phy_sfp_external_phy(struct axgbe_port *pdata)
560a5c72737SRavi Kumar {
561a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
562a5c72737SRavi Kumar 
563a5c72737SRavi Kumar 	if (!phy_data->sfp_changed)
564a5c72737SRavi Kumar 		return;
565a5c72737SRavi Kumar 
566a5c72737SRavi Kumar 	phy_data->sfp_phy_avail = 0;
567a5c72737SRavi Kumar 
568a5c72737SRavi Kumar 	if (phy_data->sfp_base != AXGBE_SFP_BASE_1000_T)
569a5c72737SRavi Kumar 		return;
570a5c72737SRavi Kumar }
571a5c72737SRavi Kumar 
572a5c72737SRavi Kumar static bool axgbe_phy_belfuse_parse_quirks(struct axgbe_port *pdata)
573a5c72737SRavi Kumar {
574a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
575a5c72737SRavi Kumar 	struct axgbe_sfp_eeprom *sfp_eeprom = &phy_data->sfp_eeprom;
576a5c72737SRavi Kumar 
577a5c72737SRavi Kumar 	if (memcmp(&sfp_eeprom->base[AXGBE_SFP_BASE_VENDOR_NAME],
57827578231SAndy Green 		   AXGBE_BEL_FUSE_VENDOR, strlen(AXGBE_BEL_FUSE_VENDOR)))
579a5c72737SRavi Kumar 		return false;
580a5c72737SRavi Kumar 
581a5c72737SRavi Kumar 	if (!memcmp(&sfp_eeprom->base[AXGBE_SFP_BASE_VENDOR_PN],
58227578231SAndy Green 		    AXGBE_BEL_FUSE_PARTNO, strlen(AXGBE_BEL_FUSE_PARTNO))) {
583a5c72737SRavi Kumar 		phy_data->sfp_base = AXGBE_SFP_BASE_1000_SX;
584a5c72737SRavi Kumar 		phy_data->sfp_cable = AXGBE_SFP_CABLE_ACTIVE;
585a5c72737SRavi Kumar 		phy_data->sfp_speed = AXGBE_SFP_SPEED_1000;
586a5c72737SRavi Kumar 		return true;
587a5c72737SRavi Kumar 	}
588a5c72737SRavi Kumar 
589a5c72737SRavi Kumar 	return false;
590a5c72737SRavi Kumar }
591a5c72737SRavi Kumar 
592a5c72737SRavi Kumar static bool axgbe_phy_sfp_parse_quirks(struct axgbe_port *pdata)
593a5c72737SRavi Kumar {
594a5c72737SRavi Kumar 	if (axgbe_phy_belfuse_parse_quirks(pdata))
595a5c72737SRavi Kumar 		return true;
596a5c72737SRavi Kumar 
597a5c72737SRavi Kumar 	return false;
598a5c72737SRavi Kumar }
599a5c72737SRavi Kumar 
600a5c72737SRavi Kumar static void axgbe_phy_sfp_parse_eeprom(struct axgbe_port *pdata)
601a5c72737SRavi Kumar {
602a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
603a5c72737SRavi Kumar 	struct axgbe_sfp_eeprom *sfp_eeprom = &phy_data->sfp_eeprom;
604a5c72737SRavi Kumar 	uint8_t *sfp_base;
605a5c72737SRavi Kumar 
606a5c72737SRavi Kumar 	sfp_base = sfp_eeprom->base;
607a5c72737SRavi Kumar 
608a5c72737SRavi Kumar 	if (sfp_base[AXGBE_SFP_BASE_ID] != AXGBE_SFP_ID_SFP)
609a5c72737SRavi Kumar 		return;
610a5c72737SRavi Kumar 
611a5c72737SRavi Kumar 	if (sfp_base[AXGBE_SFP_BASE_EXT_ID] != AXGBE_SFP_EXT_ID_SFP)
612a5c72737SRavi Kumar 		return;
613a5c72737SRavi Kumar 
614936e294cSGirish Nandibasappa 	axgbe_phy_sfp_parse_quirks(pdata);
615a5c72737SRavi Kumar 
616a5c72737SRavi Kumar 	/* Assume ACTIVE cable unless told it is PASSIVE */
617a5c72737SRavi Kumar 	if (sfp_base[AXGBE_SFP_BASE_CABLE] & AXGBE_SFP_BASE_CABLE_PASSIVE) {
618a5c72737SRavi Kumar 		phy_data->sfp_cable = AXGBE_SFP_CABLE_PASSIVE;
619a5c72737SRavi Kumar 		phy_data->sfp_cable_len = sfp_base[AXGBE_SFP_BASE_CU_CABLE_LEN];
620a5c72737SRavi Kumar 	} else {
621a5c72737SRavi Kumar 		phy_data->sfp_cable = AXGBE_SFP_CABLE_ACTIVE;
622a5c72737SRavi Kumar 	}
623a5c72737SRavi Kumar 
624a5c72737SRavi Kumar 	/* Determine the type of SFP */
625a5c72737SRavi Kumar 	if (sfp_base[AXGBE_SFP_BASE_10GBE_CC] & AXGBE_SFP_BASE_10GBE_CC_SR)
626a5c72737SRavi Kumar 		phy_data->sfp_base = AXGBE_SFP_BASE_10000_SR;
627a5c72737SRavi Kumar 	else if (sfp_base[AXGBE_SFP_BASE_10GBE_CC] & AXGBE_SFP_BASE_10GBE_CC_LR)
628a5c72737SRavi Kumar 		phy_data->sfp_base = AXGBE_SFP_BASE_10000_LR;
629a5c72737SRavi Kumar 	else if (sfp_base[AXGBE_SFP_BASE_10GBE_CC] &
630a5c72737SRavi Kumar 		 AXGBE_SFP_BASE_10GBE_CC_LRM)
631a5c72737SRavi Kumar 		phy_data->sfp_base = AXGBE_SFP_BASE_10000_LRM;
632a5c72737SRavi Kumar 	else if (sfp_base[AXGBE_SFP_BASE_10GBE_CC] & AXGBE_SFP_BASE_10GBE_CC_ER)
633a5c72737SRavi Kumar 		phy_data->sfp_base = AXGBE_SFP_BASE_10000_ER;
634a5c72737SRavi Kumar 	else if (sfp_base[AXGBE_SFP_BASE_1GBE_CC] & AXGBE_SFP_BASE_1GBE_CC_SX)
635a5c72737SRavi Kumar 		phy_data->sfp_base = AXGBE_SFP_BASE_1000_SX;
636a5c72737SRavi Kumar 	else if (sfp_base[AXGBE_SFP_BASE_1GBE_CC] & AXGBE_SFP_BASE_1GBE_CC_LX)
637a5c72737SRavi Kumar 		phy_data->sfp_base = AXGBE_SFP_BASE_1000_LX;
638a5c72737SRavi Kumar 	else if (sfp_base[AXGBE_SFP_BASE_1GBE_CC] & AXGBE_SFP_BASE_1GBE_CC_CX)
639a5c72737SRavi Kumar 		phy_data->sfp_base = AXGBE_SFP_BASE_1000_CX;
640a5c72737SRavi Kumar 	else if (sfp_base[AXGBE_SFP_BASE_1GBE_CC] & AXGBE_SFP_BASE_1GBE_CC_T)
641a5c72737SRavi Kumar 		phy_data->sfp_base = AXGBE_SFP_BASE_1000_T;
642a5c72737SRavi Kumar 	else if ((phy_data->sfp_cable == AXGBE_SFP_CABLE_PASSIVE) &&
643a5c72737SRavi Kumar 		 axgbe_phy_sfp_bit_rate(sfp_eeprom, AXGBE_SFP_SPEED_10000))
644a5c72737SRavi Kumar 		phy_data->sfp_base = AXGBE_SFP_BASE_10000_CR;
645a5c72737SRavi Kumar 
646a5c72737SRavi Kumar 	switch (phy_data->sfp_base) {
647a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_T:
648a5c72737SRavi Kumar 		phy_data->sfp_speed = AXGBE_SFP_SPEED_100_1000;
649a5c72737SRavi Kumar 		break;
650a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_SX:
651a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_LX:
652a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_CX:
653a5c72737SRavi Kumar 		phy_data->sfp_speed = AXGBE_SFP_SPEED_1000;
654a5c72737SRavi Kumar 		break;
655a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_SR:
656a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_LR:
657a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_LRM:
658a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_ER:
659a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_CR:
660a5c72737SRavi Kumar 		phy_data->sfp_speed = AXGBE_SFP_SPEED_10000;
661a5c72737SRavi Kumar 		break;
662a5c72737SRavi Kumar 	default:
663a5c72737SRavi Kumar 		break;
664a5c72737SRavi Kumar 	}
665a5c72737SRavi Kumar }
666a5c72737SRavi Kumar 
667a5c72737SRavi Kumar static bool axgbe_phy_sfp_verify_eeprom(uint8_t cc_in, uint8_t *buf,
668a5c72737SRavi Kumar 					unsigned int len)
669a5c72737SRavi Kumar {
670a5c72737SRavi Kumar 	uint8_t cc;
671a5c72737SRavi Kumar 
672a5c72737SRavi Kumar 	for (cc = 0; len; buf++, len--)
673a5c72737SRavi Kumar 		cc += *buf;
674a5c72737SRavi Kumar 
675a5c72737SRavi Kumar 	return (cc == cc_in) ? true : false;
676a5c72737SRavi Kumar }
677a5c72737SRavi Kumar 
678a5c72737SRavi Kumar static int axgbe_phy_sfp_read_eeprom(struct axgbe_port *pdata)
679a5c72737SRavi Kumar {
680a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
681a5c72737SRavi Kumar 	struct axgbe_sfp_eeprom sfp_eeprom;
682a5c72737SRavi Kumar 	uint8_t eeprom_addr;
683a5c72737SRavi Kumar 	int ret;
684a5c72737SRavi Kumar 
685a5c72737SRavi Kumar 	ret = axgbe_phy_sfp_get_mux(pdata);
686a5c72737SRavi Kumar 	if (ret) {
687a5c72737SRavi Kumar 		PMD_DRV_LOG(ERR, "I2C error setting SFP MUX\n");
688a5c72737SRavi Kumar 		return ret;
689a5c72737SRavi Kumar 	}
690a5c72737SRavi Kumar 
691a5c72737SRavi Kumar 	/* Read the SFP serial ID eeprom */
692a5c72737SRavi Kumar 	eeprom_addr = 0;
693a5c72737SRavi Kumar 	ret = axgbe_phy_i2c_read(pdata, AXGBE_SFP_SERIAL_ID_ADDRESS,
694a5c72737SRavi Kumar 				 &eeprom_addr, sizeof(eeprom_addr),
695a5c72737SRavi Kumar 				 &sfp_eeprom, sizeof(sfp_eeprom));
696a5c72737SRavi Kumar 	if (ret) {
697a5c72737SRavi Kumar 		PMD_DRV_LOG(ERR, "I2C error reading SFP EEPROM\n");
698a5c72737SRavi Kumar 		goto put;
699a5c72737SRavi Kumar 	}
700a5c72737SRavi Kumar 
701a5c72737SRavi Kumar 	/* Validate the contents read */
702a5c72737SRavi Kumar 	if (!axgbe_phy_sfp_verify_eeprom(sfp_eeprom.base[AXGBE_SFP_BASE_CC],
703a5c72737SRavi Kumar 					 sfp_eeprom.base,
704a5c72737SRavi Kumar 					 sizeof(sfp_eeprom.base) - 1)) {
705a5c72737SRavi Kumar 		ret = -EINVAL;
706a5c72737SRavi Kumar 		goto put;
707a5c72737SRavi Kumar 	}
708a5c72737SRavi Kumar 
709a5c72737SRavi Kumar 	if (!axgbe_phy_sfp_verify_eeprom(sfp_eeprom.extd[AXGBE_SFP_EXTD_CC],
710a5c72737SRavi Kumar 					 sfp_eeprom.extd,
711a5c72737SRavi Kumar 					 sizeof(sfp_eeprom.extd) - 1)) {
712a5c72737SRavi Kumar 		ret = -EINVAL;
713a5c72737SRavi Kumar 		goto put;
714a5c72737SRavi Kumar 	}
715a5c72737SRavi Kumar 
716a5c72737SRavi Kumar 	/* Check for an added or changed SFP */
717a5c72737SRavi Kumar 	if (memcmp(&phy_data->sfp_eeprom, &sfp_eeprom, sizeof(sfp_eeprom))) {
718a5c72737SRavi Kumar 		phy_data->sfp_changed = 1;
719a5c72737SRavi Kumar 		memcpy(&phy_data->sfp_eeprom, &sfp_eeprom, sizeof(sfp_eeprom));
720a5c72737SRavi Kumar 
721a5c72737SRavi Kumar 		if (sfp_eeprom.extd[AXGBE_SFP_EXTD_SFF_8472]) {
722a5c72737SRavi Kumar 			uint8_t diag_type;
723a5c72737SRavi Kumar 			diag_type = sfp_eeprom.extd[AXGBE_SFP_EXTD_DIAG];
724a5c72737SRavi Kumar 
725a5c72737SRavi Kumar 			if (!(diag_type & AXGBE_SFP_EXTD_DIAG_ADDR_CHANGE))
726a5c72737SRavi Kumar 				phy_data->sfp_diags = 1;
727a5c72737SRavi Kumar 		}
728a5c72737SRavi Kumar 	} else {
729a5c72737SRavi Kumar 		phy_data->sfp_changed = 0;
730a5c72737SRavi Kumar 	}
731a5c72737SRavi Kumar 
732a5c72737SRavi Kumar put:
733a5c72737SRavi Kumar 	axgbe_phy_sfp_put_mux(pdata);
734a5c72737SRavi Kumar 
735a5c72737SRavi Kumar 	return ret;
736a5c72737SRavi Kumar }
737a5c72737SRavi Kumar 
738a5c72737SRavi Kumar static void axgbe_phy_sfp_signals(struct axgbe_port *pdata)
739a5c72737SRavi Kumar {
740a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
741a5c72737SRavi Kumar 	unsigned int gpio_input;
742a5c72737SRavi Kumar 	u8 gpio_reg, gpio_ports[2];
743a5c72737SRavi Kumar 	int ret;
744a5c72737SRavi Kumar 
745a5c72737SRavi Kumar 	/* Read the input port registers */
746a5c72737SRavi Kumar 	gpio_reg = 0;
747a5c72737SRavi Kumar 	ret = axgbe_phy_i2c_read(pdata, phy_data->sfp_gpio_address,
748a5c72737SRavi Kumar 				 &gpio_reg, sizeof(gpio_reg),
749a5c72737SRavi Kumar 				 gpio_ports, sizeof(gpio_ports));
750a5c72737SRavi Kumar 	if (ret) {
751a5c72737SRavi Kumar 		PMD_DRV_LOG(ERR, "I2C error reading SFP GPIOs\n");
752a5c72737SRavi Kumar 		return;
753a5c72737SRavi Kumar 	}
754a5c72737SRavi Kumar 
755a5c72737SRavi Kumar 	gpio_input = (gpio_ports[1] << 8) | gpio_ports[0];
756a5c72737SRavi Kumar 
757a5c72737SRavi Kumar 	if (phy_data->sfp_gpio_mask & AXGBE_GPIO_NO_MOD_ABSENT) {
758a5c72737SRavi Kumar 		/* No GPIO, just assume the module is present for now */
759a5c72737SRavi Kumar 		phy_data->sfp_mod_absent = 0;
760a5c72737SRavi Kumar 	} else {
761a5c72737SRavi Kumar 		if (!(gpio_input & (1 << phy_data->sfp_gpio_mod_absent)))
762a5c72737SRavi Kumar 			phy_data->sfp_mod_absent = 0;
763a5c72737SRavi Kumar 	}
764a5c72737SRavi Kumar 
765a5c72737SRavi Kumar 	if (!(phy_data->sfp_gpio_mask & AXGBE_GPIO_NO_RX_LOS) &&
766a5c72737SRavi Kumar 	    (gpio_input & (1 << phy_data->sfp_gpio_rx_los)))
767a5c72737SRavi Kumar 		phy_data->sfp_rx_los = 1;
768a5c72737SRavi Kumar 
769a5c72737SRavi Kumar 	if (!(phy_data->sfp_gpio_mask & AXGBE_GPIO_NO_TX_FAULT) &&
770a5c72737SRavi Kumar 	    (gpio_input & (1 << phy_data->sfp_gpio_tx_fault)))
771a5c72737SRavi Kumar 		phy_data->sfp_tx_fault = 1;
772a5c72737SRavi Kumar }
773a5c72737SRavi Kumar 
774a5c72737SRavi Kumar static void axgbe_phy_sfp_mod_absent(struct axgbe_port *pdata)
775a5c72737SRavi Kumar {
776a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
777a5c72737SRavi Kumar 
778a5c72737SRavi Kumar 	phy_data->sfp_mod_absent = 1;
779a5c72737SRavi Kumar 	phy_data->sfp_phy_avail = 0;
780a5c72737SRavi Kumar 	memset(&phy_data->sfp_eeprom, 0, sizeof(phy_data->sfp_eeprom));
781a5c72737SRavi Kumar }
782a5c72737SRavi Kumar 
783a5c72737SRavi Kumar static void axgbe_phy_sfp_reset(struct axgbe_phy_data *phy_data)
784a5c72737SRavi Kumar {
785a5c72737SRavi Kumar 	phy_data->sfp_rx_los = 0;
786a5c72737SRavi Kumar 	phy_data->sfp_tx_fault = 0;
787a5c72737SRavi Kumar 	phy_data->sfp_mod_absent = 1;
788a5c72737SRavi Kumar 	phy_data->sfp_diags = 0;
789a5c72737SRavi Kumar 	phy_data->sfp_base = AXGBE_SFP_BASE_UNKNOWN;
790a5c72737SRavi Kumar 	phy_data->sfp_cable = AXGBE_SFP_CABLE_UNKNOWN;
791a5c72737SRavi Kumar 	phy_data->sfp_speed = AXGBE_SFP_SPEED_UNKNOWN;
792a5c72737SRavi Kumar }
793a5c72737SRavi Kumar 
7944216cdc0SChandu Babu N static const char *axgbe_base_as_string(enum axgbe_sfp_base sfp_base)
7954216cdc0SChandu Babu N {
7964216cdc0SChandu Babu N 	switch (sfp_base) {
7974216cdc0SChandu Babu N 	case AXGBE_SFP_BASE_1000_T:
7984216cdc0SChandu Babu N 		return "1G_T";
7994216cdc0SChandu Babu N 	case AXGBE_SFP_BASE_1000_SX:
8004216cdc0SChandu Babu N 		return "1G_SX";
8014216cdc0SChandu Babu N 	case AXGBE_SFP_BASE_1000_LX:
8024216cdc0SChandu Babu N 		return "1G_LX";
8034216cdc0SChandu Babu N 	case AXGBE_SFP_BASE_1000_CX:
8044216cdc0SChandu Babu N 		return "1G_CX";
8054216cdc0SChandu Babu N 	case AXGBE_SFP_BASE_10000_SR:
8064216cdc0SChandu Babu N 		return "10G_SR";
8074216cdc0SChandu Babu N 	case AXGBE_SFP_BASE_10000_LR:
8084216cdc0SChandu Babu N 		return "10G_LR";
8094216cdc0SChandu Babu N 	case AXGBE_SFP_BASE_10000_LRM:
8104216cdc0SChandu Babu N 		return "10G_LRM";
8114216cdc0SChandu Babu N 	case AXGBE_SFP_BASE_10000_ER:
8124216cdc0SChandu Babu N 		return "10G_ER";
8134216cdc0SChandu Babu N 	case AXGBE_SFP_BASE_10000_CR:
8144216cdc0SChandu Babu N 		return "10G_CR";
8154216cdc0SChandu Babu N 	default:
8164216cdc0SChandu Babu N 		return "Unknown";
8174216cdc0SChandu Babu N 	}
8184216cdc0SChandu Babu N }
8194216cdc0SChandu Babu N 
820a5c72737SRavi Kumar static void axgbe_phy_sfp_detect(struct axgbe_port *pdata)
821a5c72737SRavi Kumar {
822a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
823a5c72737SRavi Kumar 	int ret;
824a5c72737SRavi Kumar 
825a5c72737SRavi Kumar 	/* Reset the SFP signals and info */
826a5c72737SRavi Kumar 	axgbe_phy_sfp_reset(phy_data);
827a5c72737SRavi Kumar 
828a5c72737SRavi Kumar 	ret = axgbe_phy_get_comm_ownership(pdata);
829a5c72737SRavi Kumar 	if (ret)
830a5c72737SRavi Kumar 		return;
831a5c72737SRavi Kumar 
832a5c72737SRavi Kumar 	/* Read the SFP signals and check for module presence */
833a5c72737SRavi Kumar 	axgbe_phy_sfp_signals(pdata);
834a5c72737SRavi Kumar 	if (phy_data->sfp_mod_absent) {
835a5c72737SRavi Kumar 		axgbe_phy_sfp_mod_absent(pdata);
836a5c72737SRavi Kumar 		goto put;
837a5c72737SRavi Kumar 	}
838a5c72737SRavi Kumar 
839a5c72737SRavi Kumar 	ret = axgbe_phy_sfp_read_eeprom(pdata);
840a5c72737SRavi Kumar 	if (ret) {
841a5c72737SRavi Kumar 		/* Treat any error as if there isn't an SFP plugged in */
842a5c72737SRavi Kumar 		axgbe_phy_sfp_reset(phy_data);
843a5c72737SRavi Kumar 		axgbe_phy_sfp_mod_absent(pdata);
844a5c72737SRavi Kumar 		goto put;
845a5c72737SRavi Kumar 	}
846a5c72737SRavi Kumar 
847a5c72737SRavi Kumar 	axgbe_phy_sfp_parse_eeprom(pdata);
848a5c72737SRavi Kumar 	axgbe_phy_sfp_external_phy(pdata);
849a5c72737SRavi Kumar 
8504216cdc0SChandu Babu N 	PMD_DRV_LOG(DEBUG, "SFP Base: %s\n",
8514216cdc0SChandu Babu N 		    axgbe_base_as_string(phy_data->sfp_base));
8524216cdc0SChandu Babu N 
853a5c72737SRavi Kumar put:
854a5c72737SRavi Kumar 	axgbe_phy_sfp_phy_settings(pdata);
855a5c72737SRavi Kumar 	axgbe_phy_put_comm_ownership(pdata);
856a5c72737SRavi Kumar }
857a5c72737SRavi Kumar 
858a5c72737SRavi Kumar static void axgbe_phy_phydev_flowctrl(struct axgbe_port *pdata)
859a5c72737SRavi Kumar {
860a5c72737SRavi Kumar 	pdata->phy.tx_pause = 0;
861a5c72737SRavi Kumar 	pdata->phy.rx_pause = 0;
862a5c72737SRavi Kumar }
863a5c72737SRavi Kumar 
864a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_an73_redrv_outcome(struct axgbe_port *pdata)
865a5c72737SRavi Kumar {
866a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
867a5c72737SRavi Kumar 	enum axgbe_mode mode;
868a5c72737SRavi Kumar 	unsigned int ad_reg, lp_reg;
869a5c72737SRavi Kumar 
870a5c72737SRavi Kumar 	pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
871a5c72737SRavi Kumar 	pdata->phy.lp_advertising |= ADVERTISED_Backplane;
872a5c72737SRavi Kumar 
873a5c72737SRavi Kumar 	/* Use external PHY to determine flow control */
874a5c72737SRavi Kumar 	if (pdata->phy.pause_autoneg)
875a5c72737SRavi Kumar 		axgbe_phy_phydev_flowctrl(pdata);
876a5c72737SRavi Kumar 
877a5c72737SRavi Kumar 	/* Compare Advertisement and Link Partner register 2 */
878a5c72737SRavi Kumar 	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
879a5c72737SRavi Kumar 	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
880a5c72737SRavi Kumar 	if (lp_reg & 0x80)
881a5c72737SRavi Kumar 		pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full;
882a5c72737SRavi Kumar 	if (lp_reg & 0x20)
883a5c72737SRavi Kumar 		pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full;
884a5c72737SRavi Kumar 
885a5c72737SRavi Kumar 	ad_reg &= lp_reg;
886a5c72737SRavi Kumar 	if (ad_reg & 0x80) {
887a5c72737SRavi Kumar 		switch (phy_data->port_mode) {
888a5c72737SRavi Kumar 		case AXGBE_PORT_MODE_BACKPLANE:
889443ab5aaSSelwin Sebastian 		case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG:
890a5c72737SRavi Kumar 			mode = AXGBE_MODE_KR;
891a5c72737SRavi Kumar 			break;
892a5c72737SRavi Kumar 		default:
893a5c72737SRavi Kumar 			mode = AXGBE_MODE_SFI;
894a5c72737SRavi Kumar 			break;
895a5c72737SRavi Kumar 		}
896a5c72737SRavi Kumar 	} else if (ad_reg & 0x20) {
897a5c72737SRavi Kumar 		switch (phy_data->port_mode) {
898a5c72737SRavi Kumar 		case AXGBE_PORT_MODE_BACKPLANE:
899443ab5aaSSelwin Sebastian 		case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG:
900a5c72737SRavi Kumar 			mode = AXGBE_MODE_KX_1000;
901a5c72737SRavi Kumar 			break;
902a5c72737SRavi Kumar 		case AXGBE_PORT_MODE_1000BASE_X:
903a5c72737SRavi Kumar 			mode = AXGBE_MODE_X;
904a5c72737SRavi Kumar 			break;
905a5c72737SRavi Kumar 		case AXGBE_PORT_MODE_SFP:
906a5c72737SRavi Kumar 			switch (phy_data->sfp_base) {
907a5c72737SRavi Kumar 			case AXGBE_SFP_BASE_1000_T:
908a5c72737SRavi Kumar 				mode = AXGBE_MODE_SGMII_1000;
909a5c72737SRavi Kumar 				break;
910a5c72737SRavi Kumar 			case AXGBE_SFP_BASE_1000_SX:
911a5c72737SRavi Kumar 			case AXGBE_SFP_BASE_1000_LX:
912a5c72737SRavi Kumar 			case AXGBE_SFP_BASE_1000_CX:
913a5c72737SRavi Kumar 			default:
914a5c72737SRavi Kumar 				mode = AXGBE_MODE_X;
915a5c72737SRavi Kumar 				break;
916a5c72737SRavi Kumar 			}
917a5c72737SRavi Kumar 			break;
918a5c72737SRavi Kumar 		default:
919a5c72737SRavi Kumar 			mode = AXGBE_MODE_SGMII_1000;
920a5c72737SRavi Kumar 			break;
921a5c72737SRavi Kumar 		}
922a5c72737SRavi Kumar 	} else {
923a5c72737SRavi Kumar 		mode = AXGBE_MODE_UNKNOWN;
924a5c72737SRavi Kumar 	}
925a5c72737SRavi Kumar 
926a5c72737SRavi Kumar 	/* Compare Advertisement and Link Partner register 3 */
927a5c72737SRavi Kumar 	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
928a5c72737SRavi Kumar 	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
929a5c72737SRavi Kumar 	if (lp_reg & 0xc000)
930a5c72737SRavi Kumar 		pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC;
931a5c72737SRavi Kumar 
932a5c72737SRavi Kumar 	return mode;
933a5c72737SRavi Kumar }
934a5c72737SRavi Kumar 
935a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_an73_outcome(struct axgbe_port *pdata)
936a5c72737SRavi Kumar {
937a5c72737SRavi Kumar 	enum axgbe_mode mode;
938a5c72737SRavi Kumar 	unsigned int ad_reg, lp_reg;
939a5c72737SRavi Kumar 
940a5c72737SRavi Kumar 	pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
941a5c72737SRavi Kumar 	pdata->phy.lp_advertising |= ADVERTISED_Backplane;
942a5c72737SRavi Kumar 
943a5c72737SRavi Kumar 	/* Compare Advertisement and Link Partner register 1 */
944a5c72737SRavi Kumar 	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
945a5c72737SRavi Kumar 	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
946a5c72737SRavi Kumar 	if (lp_reg & 0x400)
947a5c72737SRavi Kumar 		pdata->phy.lp_advertising |= ADVERTISED_Pause;
948a5c72737SRavi Kumar 	if (lp_reg & 0x800)
949a5c72737SRavi Kumar 		pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause;
950a5c72737SRavi Kumar 
951a5c72737SRavi Kumar 	if (pdata->phy.pause_autoneg) {
952a5c72737SRavi Kumar 		/* Set flow control based on auto-negotiation result */
953a5c72737SRavi Kumar 		pdata->phy.tx_pause = 0;
954a5c72737SRavi Kumar 		pdata->phy.rx_pause = 0;
955a5c72737SRavi Kumar 
956a5c72737SRavi Kumar 		if (ad_reg & lp_reg & 0x400) {
957a5c72737SRavi Kumar 			pdata->phy.tx_pause = 1;
958a5c72737SRavi Kumar 			pdata->phy.rx_pause = 1;
959a5c72737SRavi Kumar 		} else if (ad_reg & lp_reg & 0x800) {
960a5c72737SRavi Kumar 			if (ad_reg & 0x400)
961a5c72737SRavi Kumar 				pdata->phy.rx_pause = 1;
962a5c72737SRavi Kumar 			else if (lp_reg & 0x400)
963a5c72737SRavi Kumar 				pdata->phy.tx_pause = 1;
964a5c72737SRavi Kumar 		}
965a5c72737SRavi Kumar 	}
966a5c72737SRavi Kumar 
967a5c72737SRavi Kumar 	/* Compare Advertisement and Link Partner register 2 */
968a5c72737SRavi Kumar 	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
969a5c72737SRavi Kumar 	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
970a5c72737SRavi Kumar 	if (lp_reg & 0x80)
971a5c72737SRavi Kumar 		pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full;
972a5c72737SRavi Kumar 	if (lp_reg & 0x20)
973a5c72737SRavi Kumar 		pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full;
974a5c72737SRavi Kumar 
975a5c72737SRavi Kumar 	ad_reg &= lp_reg;
976a5c72737SRavi Kumar 	if (ad_reg & 0x80)
977a5c72737SRavi Kumar 		mode = AXGBE_MODE_KR;
978a5c72737SRavi Kumar 	else if (ad_reg & 0x20)
979a5c72737SRavi Kumar 		mode = AXGBE_MODE_KX_1000;
980a5c72737SRavi Kumar 	else
981a5c72737SRavi Kumar 		mode = AXGBE_MODE_UNKNOWN;
982a5c72737SRavi Kumar 
983a5c72737SRavi Kumar 	/* Compare Advertisement and Link Partner register 3 */
984a5c72737SRavi Kumar 	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
985a5c72737SRavi Kumar 	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
986a5c72737SRavi Kumar 	if (lp_reg & 0xc000)
987a5c72737SRavi Kumar 		pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC;
988a5c72737SRavi Kumar 
989a5c72737SRavi Kumar 	return mode;
990a5c72737SRavi Kumar }
991a5c72737SRavi Kumar 
992102b6ec3SGirish Nandibasappa static enum axgbe_mode axgbe_phy_an37_sgmii_outcome(struct axgbe_port *pdata)
993102b6ec3SGirish Nandibasappa {
994102b6ec3SGirish Nandibasappa 	enum axgbe_mode mode;
995102b6ec3SGirish Nandibasappa 
996102b6ec3SGirish Nandibasappa 	pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
997102b6ec3SGirish Nandibasappa 	pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Full;
998102b6ec3SGirish Nandibasappa 
999102b6ec3SGirish Nandibasappa 	if (pdata->phy.pause_autoneg)
1000102b6ec3SGirish Nandibasappa 		axgbe_phy_phydev_flowctrl(pdata);
1001102b6ec3SGirish Nandibasappa 
1002102b6ec3SGirish Nandibasappa 	switch (pdata->an_status & AXGBE_SGMII_AN_LINK_SPEED) {
1003102b6ec3SGirish Nandibasappa 	case AXGBE_SGMII_AN_LINK_SPEED_100:
1004102b6ec3SGirish Nandibasappa 		if (pdata->an_status & AXGBE_SGMII_AN_LINK_DUPLEX) {
1005102b6ec3SGirish Nandibasappa 			pdata->phy.lp_advertising |= ADVERTISED_100baseT_Full;
1006102b6ec3SGirish Nandibasappa 			mode = AXGBE_MODE_SGMII_100;
1007102b6ec3SGirish Nandibasappa 		} else {
1008102b6ec3SGirish Nandibasappa 			mode = AXGBE_MODE_UNKNOWN;
1009102b6ec3SGirish Nandibasappa 		}
1010102b6ec3SGirish Nandibasappa 		break;
1011102b6ec3SGirish Nandibasappa 	case AXGBE_SGMII_AN_LINK_SPEED_1000:
1012102b6ec3SGirish Nandibasappa 		if (pdata->an_status & AXGBE_SGMII_AN_LINK_DUPLEX) {
1013102b6ec3SGirish Nandibasappa 			pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Full;
1014102b6ec3SGirish Nandibasappa 			mode = AXGBE_MODE_SGMII_1000;
1015102b6ec3SGirish Nandibasappa 		} else {
1016102b6ec3SGirish Nandibasappa 			/* Half-duplex not supported */
1017102b6ec3SGirish Nandibasappa 			mode = AXGBE_MODE_UNKNOWN;
1018102b6ec3SGirish Nandibasappa 		}
1019102b6ec3SGirish Nandibasappa 		break;
1020102b6ec3SGirish Nandibasappa 	default:
1021102b6ec3SGirish Nandibasappa 		mode = AXGBE_MODE_UNKNOWN;
1022102b6ec3SGirish Nandibasappa 		break;
1023102b6ec3SGirish Nandibasappa 	}
1024102b6ec3SGirish Nandibasappa 	return mode;
1025102b6ec3SGirish Nandibasappa }
1026102b6ec3SGirish Nandibasappa 
1027a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_an_outcome(struct axgbe_port *pdata)
1028a5c72737SRavi Kumar {
1029a5c72737SRavi Kumar 	switch (pdata->an_mode) {
1030a5c72737SRavi Kumar 	case AXGBE_AN_MODE_CL73:
1031a5c72737SRavi Kumar 		return axgbe_phy_an73_outcome(pdata);
1032a5c72737SRavi Kumar 	case AXGBE_AN_MODE_CL73_REDRV:
1033a5c72737SRavi Kumar 		return axgbe_phy_an73_redrv_outcome(pdata);
1034a5c72737SRavi Kumar 	case AXGBE_AN_MODE_CL37:
1035a5c72737SRavi Kumar 	case AXGBE_AN_MODE_CL37_SGMII:
1036102b6ec3SGirish Nandibasappa 		return axgbe_phy_an37_sgmii_outcome(pdata);
1037a5c72737SRavi Kumar 	default:
1038a5c72737SRavi Kumar 		return AXGBE_MODE_UNKNOWN;
1039a5c72737SRavi Kumar 	}
1040a5c72737SRavi Kumar }
1041a5c72737SRavi Kumar 
1042a5c72737SRavi Kumar static unsigned int axgbe_phy_an_advertising(struct axgbe_port *pdata)
1043a5c72737SRavi Kumar {
1044a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1045a5c72737SRavi Kumar 	unsigned int advertising;
1046a5c72737SRavi Kumar 
1047a5c72737SRavi Kumar 	/* Without a re-driver, just return current advertising */
1048a5c72737SRavi Kumar 	if (!phy_data->redrv)
1049a5c72737SRavi Kumar 		return pdata->phy.advertising;
1050a5c72737SRavi Kumar 
1051a5c72737SRavi Kumar 	/* With the KR re-driver we need to advertise a single speed */
1052a5c72737SRavi Kumar 	advertising = pdata->phy.advertising;
1053a5c72737SRavi Kumar 	advertising &= ~ADVERTISED_1000baseKX_Full;
1054a5c72737SRavi Kumar 	advertising &= ~ADVERTISED_10000baseKR_Full;
1055a5c72737SRavi Kumar 
1056a5c72737SRavi Kumar 	switch (phy_data->port_mode) {
1057a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE:
1058443ab5aaSSelwin Sebastian 	case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG:
1059a5c72737SRavi Kumar 		advertising |= ADVERTISED_10000baseKR_Full;
1060a5c72737SRavi Kumar 		break;
1061a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE_2500:
1062a5c72737SRavi Kumar 		advertising |= ADVERTISED_1000baseKX_Full;
1063a5c72737SRavi Kumar 		break;
1064a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_T:
1065a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_X:
1066a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_NBASE_T:
1067a5c72737SRavi Kumar 		advertising |= ADVERTISED_1000baseKX_Full;
1068a5c72737SRavi Kumar 		break;
1069a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_T:
1070a5c72737SRavi Kumar 		PMD_DRV_LOG(ERR, "10GBASE_T mode is not supported\n");
1071a5c72737SRavi Kumar 		break;
1072a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_R:
1073a5c72737SRavi Kumar 		advertising |= ADVERTISED_10000baseKR_Full;
1074a5c72737SRavi Kumar 		break;
1075a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_SFP:
1076a5c72737SRavi Kumar 		switch (phy_data->sfp_base) {
1077a5c72737SRavi Kumar 		case AXGBE_SFP_BASE_1000_T:
1078a5c72737SRavi Kumar 		case AXGBE_SFP_BASE_1000_SX:
1079a5c72737SRavi Kumar 		case AXGBE_SFP_BASE_1000_LX:
1080a5c72737SRavi Kumar 		case AXGBE_SFP_BASE_1000_CX:
1081a5c72737SRavi Kumar 			advertising |= ADVERTISED_1000baseKX_Full;
1082a5c72737SRavi Kumar 			break;
1083a5c72737SRavi Kumar 		default:
1084a5c72737SRavi Kumar 			advertising |= ADVERTISED_10000baseKR_Full;
1085a5c72737SRavi Kumar 			break;
1086a5c72737SRavi Kumar 		}
1087a5c72737SRavi Kumar 		break;
1088a5c72737SRavi Kumar 	default:
1089a5c72737SRavi Kumar 		advertising |= ADVERTISED_10000baseKR_Full;
1090a5c72737SRavi Kumar 		break;
1091a5c72737SRavi Kumar 	}
1092a5c72737SRavi Kumar 
1093a5c72737SRavi Kumar 	return advertising;
1094a5c72737SRavi Kumar }
1095a5c72737SRavi Kumar 
1096a5c72737SRavi Kumar static int axgbe_phy_an_config(struct axgbe_port *pdata __rte_unused)
1097a5c72737SRavi Kumar {
1098a5c72737SRavi Kumar 	return 0;
1099a5c72737SRavi Kumar 	/* Dummy API since there is no case to support
11007be78d02SJosh Soref 	 * external phy devices registered through kernel APIs
1101a5c72737SRavi Kumar 	 */
1102a5c72737SRavi Kumar }
1103a5c72737SRavi Kumar 
1104a5c72737SRavi Kumar static enum axgbe_an_mode axgbe_phy_an_sfp_mode(struct axgbe_phy_data *phy_data)
1105a5c72737SRavi Kumar {
1106a5c72737SRavi Kumar 	switch (phy_data->sfp_base) {
1107a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_T:
1108a5c72737SRavi Kumar 		return AXGBE_AN_MODE_CL37_SGMII;
1109a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_SX:
1110a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_LX:
1111a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_CX:
1112a5c72737SRavi Kumar 		return AXGBE_AN_MODE_CL37;
1113a5c72737SRavi Kumar 	default:
1114a5c72737SRavi Kumar 		return AXGBE_AN_MODE_NONE;
1115a5c72737SRavi Kumar 	}
1116a5c72737SRavi Kumar }
1117a5c72737SRavi Kumar 
1118a5c72737SRavi Kumar static enum axgbe_an_mode axgbe_phy_an_mode(struct axgbe_port *pdata)
1119a5c72737SRavi Kumar {
1120a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1121a5c72737SRavi Kumar 
1122a5c72737SRavi Kumar 	/* A KR re-driver will always require CL73 AN */
1123a5c72737SRavi Kumar 	if (phy_data->redrv)
1124a5c72737SRavi Kumar 		return AXGBE_AN_MODE_CL73_REDRV;
1125a5c72737SRavi Kumar 
1126a5c72737SRavi Kumar 	switch (phy_data->port_mode) {
1127a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE:
1128a5c72737SRavi Kumar 		return AXGBE_AN_MODE_CL73;
1129443ab5aaSSelwin Sebastian 	case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG:
1130a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE_2500:
1131a5c72737SRavi Kumar 		return AXGBE_AN_MODE_NONE;
1132a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_T:
1133a5c72737SRavi Kumar 		return AXGBE_AN_MODE_CL37_SGMII;
1134a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_X:
1135a5c72737SRavi Kumar 		return AXGBE_AN_MODE_CL37;
1136a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_NBASE_T:
1137a5c72737SRavi Kumar 		return AXGBE_AN_MODE_CL37_SGMII;
1138a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_T:
1139a5c72737SRavi Kumar 		return AXGBE_AN_MODE_CL73;
1140a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_R:
1141a5c72737SRavi Kumar 		return AXGBE_AN_MODE_NONE;
1142a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_SFP:
1143a5c72737SRavi Kumar 		return axgbe_phy_an_sfp_mode(phy_data);
1144a5c72737SRavi Kumar 	default:
1145a5c72737SRavi Kumar 		return AXGBE_AN_MODE_NONE;
1146a5c72737SRavi Kumar 	}
1147a5c72737SRavi Kumar }
1148a5c72737SRavi Kumar 
1149a5c72737SRavi Kumar static int axgbe_phy_set_redrv_mode_mdio(struct axgbe_port *pdata,
1150a5c72737SRavi Kumar 					 enum axgbe_phy_redrv_mode mode)
1151a5c72737SRavi Kumar {
1152a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1153a5c72737SRavi Kumar 	u16 redrv_reg, redrv_val;
1154a5c72737SRavi Kumar 
1155a5c72737SRavi Kumar 	redrv_reg = AXGBE_PHY_REDRV_MODE_REG + (phy_data->redrv_lane * 0x1000);
1156a5c72737SRavi Kumar 	redrv_val = (u16)mode;
1157a5c72737SRavi Kumar 
1158a5c72737SRavi Kumar 	return pdata->hw_if.write_ext_mii_regs(pdata, phy_data->redrv_addr,
1159a5c72737SRavi Kumar 					       redrv_reg, redrv_val);
1160a5c72737SRavi Kumar }
1161a5c72737SRavi Kumar 
1162a5c72737SRavi Kumar static int axgbe_phy_set_redrv_mode_i2c(struct axgbe_port *pdata,
1163a5c72737SRavi Kumar 					enum axgbe_phy_redrv_mode mode)
1164a5c72737SRavi Kumar {
1165a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1166a5c72737SRavi Kumar 	unsigned int redrv_reg;
1167a5c72737SRavi Kumar 	int ret;
1168a5c72737SRavi Kumar 
1169a5c72737SRavi Kumar 	/* Calculate the register to write */
1170a5c72737SRavi Kumar 	redrv_reg = AXGBE_PHY_REDRV_MODE_REG + (phy_data->redrv_lane * 0x1000);
1171a5c72737SRavi Kumar 
1172a5c72737SRavi Kumar 	ret = axgbe_phy_redrv_write(pdata, redrv_reg, mode);
1173a5c72737SRavi Kumar 
1174a5c72737SRavi Kumar 	return ret;
1175a5c72737SRavi Kumar }
1176a5c72737SRavi Kumar 
1177a5c72737SRavi Kumar static void axgbe_phy_set_redrv_mode(struct axgbe_port *pdata)
1178a5c72737SRavi Kumar {
1179a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1180a5c72737SRavi Kumar 	enum axgbe_phy_redrv_mode mode;
1181a5c72737SRavi Kumar 	int ret;
1182a5c72737SRavi Kumar 
1183a5c72737SRavi Kumar 	if (!phy_data->redrv)
1184a5c72737SRavi Kumar 		return;
1185a5c72737SRavi Kumar 
1186a5c72737SRavi Kumar 	mode = AXGBE_PHY_REDRV_MODE_CX;
1187a5c72737SRavi Kumar 	if ((phy_data->port_mode == AXGBE_PORT_MODE_SFP) &&
1188a5c72737SRavi Kumar 	    (phy_data->sfp_base != AXGBE_SFP_BASE_1000_CX) &&
1189a5c72737SRavi Kumar 	    (phy_data->sfp_base != AXGBE_SFP_BASE_10000_CR))
1190a5c72737SRavi Kumar 		mode = AXGBE_PHY_REDRV_MODE_SR;
1191a5c72737SRavi Kumar 
1192a5c72737SRavi Kumar 	ret = axgbe_phy_get_comm_ownership(pdata);
1193a5c72737SRavi Kumar 	if (ret)
1194a5c72737SRavi Kumar 		return;
1195a5c72737SRavi Kumar 
1196a5c72737SRavi Kumar 	if (phy_data->redrv_if)
1197a5c72737SRavi Kumar 		axgbe_phy_set_redrv_mode_i2c(pdata, mode);
1198a5c72737SRavi Kumar 	else
1199a5c72737SRavi Kumar 		axgbe_phy_set_redrv_mode_mdio(pdata, mode);
1200a5c72737SRavi Kumar 
1201a5c72737SRavi Kumar 	axgbe_phy_put_comm_ownership(pdata);
1202a5c72737SRavi Kumar }
1203a5c72737SRavi Kumar 
1204cd48955bSSelwin Sebastian static void axgbe_phy_rx_reset(struct axgbe_port *pdata)
1205cd48955bSSelwin Sebastian {
1206cd48955bSSelwin Sebastian 	int reg;
1207cd48955bSSelwin Sebastian 
1208cd48955bSSelwin Sebastian 	reg = XMDIO_READ_BITS(pdata, MDIO_MMD_PCS, MDIO_PCS_DIGITAL_STAT,
1209cd48955bSSelwin Sebastian 			      XGBE_PCS_PSEQ_STATE_MASK);
1210cd48955bSSelwin Sebastian 	if (reg == XGBE_PCS_PSEQ_STATE_POWER_GOOD) {
1211cd48955bSSelwin Sebastian 		/* Mailbox command timed out, reset of RX block is required.
1212cd48955bSSelwin Sebastian 		 * This can be done by asseting the reset bit and wait for
1213cd48955bSSelwin Sebastian 		 * its compeletion.
1214cd48955bSSelwin Sebastian 		 */
1215cd48955bSSelwin Sebastian 		XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1,
1216cd48955bSSelwin Sebastian 				 XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_ON);
1217cd48955bSSelwin Sebastian 		rte_delay_us(20);
1218cd48955bSSelwin Sebastian 		XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1,
1219cd48955bSSelwin Sebastian 				 XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_OFF);
1220cd48955bSSelwin Sebastian 		rte_delay_us(45);
1221cd48955bSSelwin Sebastian 		PMD_DRV_LOG(ERR, "firmware mailbox reset performed\n");
1222cd48955bSSelwin Sebastian 	}
1223cd48955bSSelwin Sebastian }
1224cd48955bSSelwin Sebastian 
1225cd48955bSSelwin Sebastian 
122609b0a36cSSelwin Sebastian static void axgbe_phy_pll_ctrl(struct axgbe_port *pdata, bool enable)
122709b0a36cSSelwin Sebastian {
122809b0a36cSSelwin Sebastian 	XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_MISC_CTRL0,
122909b0a36cSSelwin Sebastian 			XGBE_PMA_PLL_CTRL_MASK,
123009b0a36cSSelwin Sebastian 			enable ? XGBE_PMA_PLL_CTRL_SET
123109b0a36cSSelwin Sebastian 			: XGBE_PMA_PLL_CTRL_CLEAR);
123209b0a36cSSelwin Sebastian 
123309b0a36cSSelwin Sebastian 	/* Wait for command to complete */
123409b0a36cSSelwin Sebastian 	rte_delay_us(150);
123509b0a36cSSelwin Sebastian }
123609b0a36cSSelwin Sebastian 
12370df8d8dfSSelwin Sebastian static void axgbe_phy_perform_ratechange(struct axgbe_port *pdata,
12380df8d8dfSSelwin Sebastian 					unsigned int cmd, unsigned int sub_cmd)
1239a5c72737SRavi Kumar {
12400df8d8dfSSelwin Sebastian 	unsigned int s0 = 0;
12410df8d8dfSSelwin Sebastian 	unsigned int wait;
124209b0a36cSSelwin Sebastian 	/* Clear the PLL so that it helps in power down sequence */
124309b0a36cSSelwin Sebastian 	axgbe_phy_pll_ctrl(pdata, false);
124409b0a36cSSelwin Sebastian 
12454216cdc0SChandu Babu N 	/* Log if a previous command did not complete */
1246cd48955bSSelwin Sebastian 	if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) {
12474216cdc0SChandu Babu N 		PMD_DRV_LOG(NOTICE, "firmware mailbox not ready for command\n");
1248cd48955bSSelwin Sebastian 		axgbe_phy_rx_reset(pdata);
1249cd48955bSSelwin Sebastian 	}
1250a5c72737SRavi Kumar 
12510df8d8dfSSelwin Sebastian 	/* Construct the command */
12520df8d8dfSSelwin Sebastian 	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, cmd);
12530df8d8dfSSelwin Sebastian 	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, sub_cmd);
12540df8d8dfSSelwin Sebastian 
12550df8d8dfSSelwin Sebastian 	/* Issue the command */
12560df8d8dfSSelwin Sebastian 	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0);
12570df8d8dfSSelwin Sebastian 	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
12580df8d8dfSSelwin Sebastian 	XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
1259a5c72737SRavi Kumar 
1260a5c72737SRavi Kumar 	/* Wait for command to complete */
1261a5c72737SRavi Kumar 	wait = AXGBE_RATECHANGE_COUNT;
1262a5c72737SRavi Kumar 	while (wait--) {
1263a5c72737SRavi Kumar 		if (!XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS))
126409b0a36cSSelwin Sebastian 			goto reenable_pll;
1265a5c72737SRavi Kumar 		rte_delay_us(1500);
1266a5c72737SRavi Kumar 	}
1267cd48955bSSelwin Sebastian 	PMD_DRV_LOG(NOTICE, "firmware mailbox command did not complete\n");
1268cd48955bSSelwin Sebastian 	/* Reset on error */
1269cd48955bSSelwin Sebastian 	axgbe_phy_rx_reset(pdata);
127009b0a36cSSelwin Sebastian 
127109b0a36cSSelwin Sebastian reenable_pll:
127209b0a36cSSelwin Sebastian 	 /* Re-enable the PLL control */
127309b0a36cSSelwin Sebastian 	axgbe_phy_pll_ctrl(pdata, true);
127409b0a36cSSelwin Sebastian 
12754216cdc0SChandu Babu N 	PMD_DRV_LOG(NOTICE, "firmware mailbox command did not complete\n");
1276a5c72737SRavi Kumar }
1277a5c72737SRavi Kumar 
1278a5c72737SRavi Kumar static void axgbe_phy_rrc(struct axgbe_port *pdata)
1279a5c72737SRavi Kumar {
1280a5c72737SRavi Kumar 
1281a5c72737SRavi Kumar 
1282a5c72737SRavi Kumar 	/* Receiver Reset Cycle */
12830df8d8dfSSelwin Sebastian 	axgbe_phy_perform_ratechange(pdata, 5, 0);
12844216cdc0SChandu Babu N 
12854216cdc0SChandu Babu N 	PMD_DRV_LOG(DEBUG, "receiver reset complete\n");
1286a5c72737SRavi Kumar }
1287a5c72737SRavi Kumar 
1288a5c72737SRavi Kumar static void axgbe_phy_power_off(struct axgbe_port *pdata)
1289a5c72737SRavi Kumar {
1290a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1291a5c72737SRavi Kumar 
12920df8d8dfSSelwin Sebastian 	/* Power off */
12930df8d8dfSSelwin Sebastian 	axgbe_phy_perform_ratechange(pdata, 0, 0);
1294a5c72737SRavi Kumar 
1295a5c72737SRavi Kumar 	phy_data->cur_mode = AXGBE_MODE_UNKNOWN;
12964216cdc0SChandu Babu N 
12974216cdc0SChandu Babu N 	PMD_DRV_LOG(DEBUG, "phy powered off\n");
1298a5c72737SRavi Kumar }
1299a5c72737SRavi Kumar 
1300a5c72737SRavi Kumar static void axgbe_phy_sfi_mode(struct axgbe_port *pdata)
1301a5c72737SRavi Kumar {
1302a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1303a5c72737SRavi Kumar 
1304a5c72737SRavi Kumar 	axgbe_phy_set_redrv_mode(pdata);
1305a5c72737SRavi Kumar 
1306a5c72737SRavi Kumar 	/* 10G/SFI */
1307a5c72737SRavi Kumar 	if (phy_data->sfp_cable != AXGBE_SFP_CABLE_PASSIVE) {
13080df8d8dfSSelwin Sebastian 		axgbe_phy_perform_ratechange(pdata, 3, 0);
1309a5c72737SRavi Kumar 	} else {
1310a5c72737SRavi Kumar 		if (phy_data->sfp_cable_len <= 1)
13110df8d8dfSSelwin Sebastian 			axgbe_phy_perform_ratechange(pdata, 3, 1);
1312a5c72737SRavi Kumar 		else if (phy_data->sfp_cable_len <= 3)
13130df8d8dfSSelwin Sebastian 			axgbe_phy_perform_ratechange(pdata, 3, 2);
1314a5c72737SRavi Kumar 		else
13150df8d8dfSSelwin Sebastian 			axgbe_phy_perform_ratechange(pdata, 3, 3);
1316a5c72737SRavi Kumar 	}
1317a5c72737SRavi Kumar 
1318a5c72737SRavi Kumar 	phy_data->cur_mode = AXGBE_MODE_SFI;
13194216cdc0SChandu Babu N 
13204216cdc0SChandu Babu N 	PMD_DRV_LOG(DEBUG, "10GbE SFI mode set\n");
1321a5c72737SRavi Kumar }
1322a5c72737SRavi Kumar 
1323a5c72737SRavi Kumar static void axgbe_phy_kr_mode(struct axgbe_port *pdata)
1324a5c72737SRavi Kumar {
1325a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1326a5c72737SRavi Kumar 
1327a5c72737SRavi Kumar 	axgbe_phy_set_redrv_mode(pdata);
1328a5c72737SRavi Kumar 
1329a5c72737SRavi Kumar 	/* 10G/KR */
13300df8d8dfSSelwin Sebastian 	axgbe_phy_perform_ratechange(pdata, 4, 0);
1331a5c72737SRavi Kumar 	phy_data->cur_mode = AXGBE_MODE_KR;
13324216cdc0SChandu Babu N 
13334216cdc0SChandu Babu N 	PMD_DRV_LOG(DEBUG, "10GbE KR mode set\n");
1334a5c72737SRavi Kumar }
1335a5c72737SRavi Kumar 
1336936e294cSGirish Nandibasappa static void axgbe_phy_kx_2500_mode(struct axgbe_port *pdata)
1337936e294cSGirish Nandibasappa {
1338936e294cSGirish Nandibasappa 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1339936e294cSGirish Nandibasappa 
1340936e294cSGirish Nandibasappa 	axgbe_phy_set_redrv_mode(pdata);
13410df8d8dfSSelwin Sebastian 
1342936e294cSGirish Nandibasappa 	/* 2.5G/KX */
13430df8d8dfSSelwin Sebastian 	axgbe_phy_perform_ratechange(pdata, 2, 0);
1344936e294cSGirish Nandibasappa 	phy_data->cur_mode = AXGBE_MODE_KX_2500;
1345936e294cSGirish Nandibasappa }
1346936e294cSGirish Nandibasappa 
1347936e294cSGirish Nandibasappa static void axgbe_phy_sgmii_1000_mode(struct axgbe_port *pdata)
1348936e294cSGirish Nandibasappa {
1349936e294cSGirish Nandibasappa 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1350936e294cSGirish Nandibasappa 
1351936e294cSGirish Nandibasappa 	axgbe_phy_set_redrv_mode(pdata);
1352936e294cSGirish Nandibasappa 
1353936e294cSGirish Nandibasappa 	/* 1G/SGMII */
13540df8d8dfSSelwin Sebastian 	axgbe_phy_perform_ratechange(pdata, 1, 2);
1355936e294cSGirish Nandibasappa 
1356936e294cSGirish Nandibasappa 	phy_data->cur_mode = AXGBE_MODE_SGMII_1000;
1357936e294cSGirish Nandibasappa }
1358936e294cSGirish Nandibasappa 
1359a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_cur_mode(struct axgbe_port *pdata)
1360a5c72737SRavi Kumar {
1361a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1362a5c72737SRavi Kumar 
1363a5c72737SRavi Kumar 	return phy_data->cur_mode;
1364a5c72737SRavi Kumar }
1365a5c72737SRavi Kumar 
1366a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_switch_baset_mode(struct axgbe_port *pdata)
1367a5c72737SRavi Kumar {
1368a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1369a5c72737SRavi Kumar 
1370a5c72737SRavi Kumar 	/* No switching if not 10GBase-T */
1371a5c72737SRavi Kumar 	if (phy_data->port_mode != AXGBE_PORT_MODE_10GBASE_T)
1372a5c72737SRavi Kumar 		return axgbe_phy_cur_mode(pdata);
1373a5c72737SRavi Kumar 
1374a5c72737SRavi Kumar 	switch (axgbe_phy_cur_mode(pdata)) {
1375a5c72737SRavi Kumar 	case AXGBE_MODE_SGMII_100:
1376a5c72737SRavi Kumar 	case AXGBE_MODE_SGMII_1000:
1377a5c72737SRavi Kumar 		return AXGBE_MODE_KR;
1378a5c72737SRavi Kumar 	case AXGBE_MODE_KR:
1379a5c72737SRavi Kumar 	default:
1380a5c72737SRavi Kumar 		return AXGBE_MODE_SGMII_1000;
1381a5c72737SRavi Kumar 	}
1382a5c72737SRavi Kumar }
1383a5c72737SRavi Kumar 
1384a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_switch_bp_2500_mode(struct axgbe_port *pdata
1385a5c72737SRavi Kumar 						     __rte_unused)
1386a5c72737SRavi Kumar {
1387a5c72737SRavi Kumar 	return AXGBE_MODE_KX_2500;
1388a5c72737SRavi Kumar }
1389a5c72737SRavi Kumar 
1390a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_switch_bp_mode(struct axgbe_port *pdata)
1391a5c72737SRavi Kumar {
1392a5c72737SRavi Kumar 	/* If we are in KR switch to KX, and vice-versa */
1393a5c72737SRavi Kumar 	switch (axgbe_phy_cur_mode(pdata)) {
1394a5c72737SRavi Kumar 	case AXGBE_MODE_KX_1000:
1395a5c72737SRavi Kumar 		return AXGBE_MODE_KR;
1396a5c72737SRavi Kumar 	case AXGBE_MODE_KR:
1397a5c72737SRavi Kumar 	default:
1398a5c72737SRavi Kumar 		return AXGBE_MODE_KX_1000;
1399a5c72737SRavi Kumar 	}
1400a5c72737SRavi Kumar }
1401a5c72737SRavi Kumar 
1402a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_switch_mode(struct axgbe_port *pdata)
1403a5c72737SRavi Kumar {
1404a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1405a5c72737SRavi Kumar 
1406a5c72737SRavi Kumar 	switch (phy_data->port_mode) {
1407a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE:
1408443ab5aaSSelwin Sebastian 	case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG:
1409a5c72737SRavi Kumar 		return axgbe_phy_switch_bp_mode(pdata);
1410a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE_2500:
1411a5c72737SRavi Kumar 		return axgbe_phy_switch_bp_2500_mode(pdata);
1412a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_T:
1413a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_NBASE_T:
1414a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_T:
1415a5c72737SRavi Kumar 		return axgbe_phy_switch_baset_mode(pdata);
1416a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_X:
1417a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_R:
1418a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_SFP:
1419a5c72737SRavi Kumar 		/* No switching, so just return current mode */
1420a5c72737SRavi Kumar 		return axgbe_phy_cur_mode(pdata);
1421a5c72737SRavi Kumar 	default:
1422a5c72737SRavi Kumar 		return AXGBE_MODE_UNKNOWN;
1423a5c72737SRavi Kumar 	}
1424a5c72737SRavi Kumar }
1425a5c72737SRavi Kumar 
1426a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_basex_mode(struct axgbe_phy_data *phy_data
1427a5c72737SRavi Kumar 						__rte_unused,
1428a5c72737SRavi Kumar 						int speed)
1429a5c72737SRavi Kumar {
1430a5c72737SRavi Kumar 	switch (speed) {
1431a5c72737SRavi Kumar 	case SPEED_1000:
1432a5c72737SRavi Kumar 		return AXGBE_MODE_X;
1433a5c72737SRavi Kumar 	case SPEED_10000:
1434a5c72737SRavi Kumar 		return AXGBE_MODE_KR;
1435a5c72737SRavi Kumar 	default:
1436a5c72737SRavi Kumar 		return AXGBE_MODE_UNKNOWN;
1437a5c72737SRavi Kumar 	}
1438a5c72737SRavi Kumar }
1439a5c72737SRavi Kumar 
1440a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_baset_mode(struct axgbe_phy_data *phy_data
1441a5c72737SRavi Kumar 						__rte_unused,
1442a5c72737SRavi Kumar 						int speed)
1443a5c72737SRavi Kumar {
1444a5c72737SRavi Kumar 	switch (speed) {
1445a5c72737SRavi Kumar 	case SPEED_100:
1446a5c72737SRavi Kumar 		return AXGBE_MODE_SGMII_100;
1447a5c72737SRavi Kumar 	case SPEED_1000:
1448a5c72737SRavi Kumar 		return AXGBE_MODE_SGMII_1000;
1449a5c72737SRavi Kumar 	case SPEED_10000:
1450a5c72737SRavi Kumar 		return AXGBE_MODE_KR;
1451a5c72737SRavi Kumar 	default:
1452a5c72737SRavi Kumar 		return AXGBE_MODE_UNKNOWN;
1453a5c72737SRavi Kumar 	}
1454a5c72737SRavi Kumar }
1455a5c72737SRavi Kumar 
1456a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_sfp_mode(struct axgbe_phy_data *phy_data,
1457a5c72737SRavi Kumar 					      int speed)
1458a5c72737SRavi Kumar {
1459a5c72737SRavi Kumar 	switch (speed) {
1460a5c72737SRavi Kumar 	case SPEED_100:
1461a5c72737SRavi Kumar 		return AXGBE_MODE_SGMII_100;
1462a5c72737SRavi Kumar 	case SPEED_1000:
1463a5c72737SRavi Kumar 		if (phy_data->sfp_base == AXGBE_SFP_BASE_1000_T)
1464a5c72737SRavi Kumar 			return AXGBE_MODE_SGMII_1000;
1465a5c72737SRavi Kumar 		else
1466a5c72737SRavi Kumar 			return AXGBE_MODE_X;
1467a5c72737SRavi Kumar 	case SPEED_10000:
1468a5c72737SRavi Kumar 	case SPEED_UNKNOWN:
1469a5c72737SRavi Kumar 		return AXGBE_MODE_SFI;
1470a5c72737SRavi Kumar 	default:
1471a5c72737SRavi Kumar 		return AXGBE_MODE_UNKNOWN;
1472a5c72737SRavi Kumar 	}
1473a5c72737SRavi Kumar }
1474a5c72737SRavi Kumar 
1475a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_bp_2500_mode(int speed)
1476a5c72737SRavi Kumar {
1477a5c72737SRavi Kumar 	switch (speed) {
1478a5c72737SRavi Kumar 	case SPEED_2500:
1479a5c72737SRavi Kumar 		return AXGBE_MODE_KX_2500;
1480a5c72737SRavi Kumar 	default:
1481a5c72737SRavi Kumar 		return AXGBE_MODE_UNKNOWN;
1482a5c72737SRavi Kumar 	}
1483a5c72737SRavi Kumar }
1484a5c72737SRavi Kumar 
1485a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_bp_mode(int speed)
1486a5c72737SRavi Kumar {
1487a5c72737SRavi Kumar 	switch (speed) {
1488a5c72737SRavi Kumar 	case SPEED_1000:
1489a5c72737SRavi Kumar 		return AXGBE_MODE_KX_1000;
1490a5c72737SRavi Kumar 	case SPEED_10000:
1491a5c72737SRavi Kumar 		return AXGBE_MODE_KR;
1492a5c72737SRavi Kumar 	default:
1493a5c72737SRavi Kumar 		return AXGBE_MODE_UNKNOWN;
1494a5c72737SRavi Kumar 	}
1495a5c72737SRavi Kumar }
1496a5c72737SRavi Kumar 
1497a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_mode(struct axgbe_port *pdata,
1498a5c72737SRavi Kumar 					  int speed)
1499a5c72737SRavi Kumar {
1500a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1501a5c72737SRavi Kumar 
1502a5c72737SRavi Kumar 	switch (phy_data->port_mode) {
1503a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE:
1504443ab5aaSSelwin Sebastian 	case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG:
1505a5c72737SRavi Kumar 		return axgbe_phy_get_bp_mode(speed);
1506a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE_2500:
1507a5c72737SRavi Kumar 		return axgbe_phy_get_bp_2500_mode(speed);
1508a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_T:
1509a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_NBASE_T:
1510a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_T:
1511a5c72737SRavi Kumar 		return axgbe_phy_get_baset_mode(phy_data, speed);
1512a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_X:
1513a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_R:
1514a5c72737SRavi Kumar 		return axgbe_phy_get_basex_mode(phy_data, speed);
1515a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_SFP:
1516a5c72737SRavi Kumar 		return axgbe_phy_get_sfp_mode(phy_data, speed);
1517a5c72737SRavi Kumar 	default:
1518a5c72737SRavi Kumar 		return AXGBE_MODE_UNKNOWN;
1519a5c72737SRavi Kumar 	}
1520a5c72737SRavi Kumar }
1521a5c72737SRavi Kumar 
1522a5c72737SRavi Kumar static void axgbe_phy_set_mode(struct axgbe_port *pdata, enum axgbe_mode mode)
1523a5c72737SRavi Kumar {
1524a5c72737SRavi Kumar 	switch (mode) {
1525a5c72737SRavi Kumar 	case AXGBE_MODE_KR:
1526a5c72737SRavi Kumar 		axgbe_phy_kr_mode(pdata);
1527a5c72737SRavi Kumar 		break;
1528a5c72737SRavi Kumar 	case AXGBE_MODE_SFI:
1529a5c72737SRavi Kumar 		axgbe_phy_sfi_mode(pdata);
1530a5c72737SRavi Kumar 		break;
1531936e294cSGirish Nandibasappa 	case AXGBE_MODE_KX_2500:
1532936e294cSGirish Nandibasappa 		axgbe_phy_kx_2500_mode(pdata);
1533936e294cSGirish Nandibasappa 		break;
1534936e294cSGirish Nandibasappa 	case AXGBE_MODE_SGMII_1000:
1535936e294cSGirish Nandibasappa 		axgbe_phy_sgmii_1000_mode(pdata);
1536936e294cSGirish Nandibasappa 		break;
1537a5c72737SRavi Kumar 	default:
1538a5c72737SRavi Kumar 		break;
1539a5c72737SRavi Kumar 	}
1540a5c72737SRavi Kumar }
1541a5c72737SRavi Kumar 
1542a5c72737SRavi Kumar static bool axgbe_phy_check_mode(struct axgbe_port *pdata,
1543a5c72737SRavi Kumar 				 enum axgbe_mode mode, u32 advert)
1544a5c72737SRavi Kumar {
1545a5c72737SRavi Kumar 	if (pdata->phy.autoneg == AUTONEG_ENABLE) {
1546a5c72737SRavi Kumar 		if (pdata->phy.advertising & advert)
1547a5c72737SRavi Kumar 			return true;
1548a5c72737SRavi Kumar 	} else {
1549a5c72737SRavi Kumar 		enum axgbe_mode cur_mode;
1550a5c72737SRavi Kumar 
1551a5c72737SRavi Kumar 		cur_mode = axgbe_phy_get_mode(pdata, pdata->phy.speed);
1552a5c72737SRavi Kumar 		if (cur_mode == mode)
1553a5c72737SRavi Kumar 			return true;
1554a5c72737SRavi Kumar 	}
1555a5c72737SRavi Kumar 
1556a5c72737SRavi Kumar 	return false;
1557a5c72737SRavi Kumar }
1558a5c72737SRavi Kumar 
1559a5c72737SRavi Kumar static bool axgbe_phy_use_basex_mode(struct axgbe_port *pdata,
1560a5c72737SRavi Kumar 				     enum axgbe_mode mode)
1561a5c72737SRavi Kumar {
1562a5c72737SRavi Kumar 	switch (mode) {
1563a5c72737SRavi Kumar 	case AXGBE_MODE_X:
1564a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1565a5c72737SRavi Kumar 					    ADVERTISED_1000baseT_Full);
1566a5c72737SRavi Kumar 	case AXGBE_MODE_KR:
1567a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1568a5c72737SRavi Kumar 					    ADVERTISED_10000baseT_Full);
1569a5c72737SRavi Kumar 	default:
1570a5c72737SRavi Kumar 		return false;
1571a5c72737SRavi Kumar 	}
1572a5c72737SRavi Kumar }
1573a5c72737SRavi Kumar 
1574a5c72737SRavi Kumar static bool axgbe_phy_use_baset_mode(struct axgbe_port *pdata,
1575a5c72737SRavi Kumar 				     enum axgbe_mode mode)
1576a5c72737SRavi Kumar {
1577a5c72737SRavi Kumar 	switch (mode) {
1578a5c72737SRavi Kumar 	case AXGBE_MODE_SGMII_100:
1579a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1580a5c72737SRavi Kumar 					    ADVERTISED_100baseT_Full);
1581a5c72737SRavi Kumar 	case AXGBE_MODE_SGMII_1000:
1582a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1583a5c72737SRavi Kumar 					    ADVERTISED_1000baseT_Full);
1584a5c72737SRavi Kumar 	case AXGBE_MODE_KR:
1585a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1586a5c72737SRavi Kumar 					    ADVERTISED_10000baseT_Full);
1587a5c72737SRavi Kumar 	default:
1588a5c72737SRavi Kumar 		return false;
1589a5c72737SRavi Kumar 	}
1590a5c72737SRavi Kumar }
1591a5c72737SRavi Kumar 
1592a5c72737SRavi Kumar static bool axgbe_phy_use_sfp_mode(struct axgbe_port *pdata,
1593a5c72737SRavi Kumar 				   enum axgbe_mode mode)
1594a5c72737SRavi Kumar {
1595a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1596a5c72737SRavi Kumar 
1597a5c72737SRavi Kumar 	switch (mode) {
1598a5c72737SRavi Kumar 	case AXGBE_MODE_X:
1599a5c72737SRavi Kumar 		if (phy_data->sfp_base == AXGBE_SFP_BASE_1000_T)
1600a5c72737SRavi Kumar 			return false;
1601a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1602a5c72737SRavi Kumar 					    ADVERTISED_1000baseT_Full);
1603a5c72737SRavi Kumar 	case AXGBE_MODE_SGMII_100:
1604a5c72737SRavi Kumar 		if (phy_data->sfp_base != AXGBE_SFP_BASE_1000_T)
1605a5c72737SRavi Kumar 			return false;
1606a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1607a5c72737SRavi Kumar 					    ADVERTISED_100baseT_Full);
1608a5c72737SRavi Kumar 	case AXGBE_MODE_SGMII_1000:
1609a5c72737SRavi Kumar 		if (phy_data->sfp_base != AXGBE_SFP_BASE_1000_T)
1610a5c72737SRavi Kumar 			return false;
1611a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1612a5c72737SRavi Kumar 					    ADVERTISED_1000baseT_Full);
1613a5c72737SRavi Kumar 	case AXGBE_MODE_SFI:
1614a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1615a5c72737SRavi Kumar 					    ADVERTISED_10000baseT_Full);
1616a5c72737SRavi Kumar 	default:
1617a5c72737SRavi Kumar 		return false;
1618a5c72737SRavi Kumar 	}
1619a5c72737SRavi Kumar }
1620a5c72737SRavi Kumar 
1621a5c72737SRavi Kumar static bool axgbe_phy_use_bp_2500_mode(struct axgbe_port *pdata,
1622a5c72737SRavi Kumar 				       enum axgbe_mode mode)
1623a5c72737SRavi Kumar {
1624a5c72737SRavi Kumar 	switch (mode) {
1625a5c72737SRavi Kumar 	case AXGBE_MODE_KX_2500:
1626a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1627a5c72737SRavi Kumar 					    ADVERTISED_2500baseX_Full);
1628a5c72737SRavi Kumar 	default:
1629a5c72737SRavi Kumar 		return false;
1630a5c72737SRavi Kumar 	}
1631a5c72737SRavi Kumar }
1632a5c72737SRavi Kumar 
1633a5c72737SRavi Kumar static bool axgbe_phy_use_bp_mode(struct axgbe_port *pdata,
1634a5c72737SRavi Kumar 				  enum axgbe_mode mode)
1635a5c72737SRavi Kumar {
1636a5c72737SRavi Kumar 	switch (mode) {
1637a5c72737SRavi Kumar 	case AXGBE_MODE_KX_1000:
1638a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1639a5c72737SRavi Kumar 					    ADVERTISED_1000baseKX_Full);
1640a5c72737SRavi Kumar 	case AXGBE_MODE_KR:
1641a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1642a5c72737SRavi Kumar 					    ADVERTISED_10000baseKR_Full);
1643a5c72737SRavi Kumar 	default:
1644a5c72737SRavi Kumar 		return false;
1645a5c72737SRavi Kumar 	}
1646a5c72737SRavi Kumar }
1647a5c72737SRavi Kumar 
1648a5c72737SRavi Kumar static bool axgbe_phy_use_mode(struct axgbe_port *pdata, enum axgbe_mode mode)
1649a5c72737SRavi Kumar {
1650a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1651a5c72737SRavi Kumar 
1652a5c72737SRavi Kumar 	switch (phy_data->port_mode) {
1653a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE:
1654443ab5aaSSelwin Sebastian 	case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG:
1655a5c72737SRavi Kumar 		return axgbe_phy_use_bp_mode(pdata, mode);
1656a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE_2500:
1657a5c72737SRavi Kumar 		return axgbe_phy_use_bp_2500_mode(pdata, mode);
1658a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_T:
1659a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_NBASE_T:
1660a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_T:
1661a5c72737SRavi Kumar 		return axgbe_phy_use_baset_mode(pdata, mode);
1662a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_X:
1663a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_R:
1664a5c72737SRavi Kumar 		return axgbe_phy_use_basex_mode(pdata, mode);
1665a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_SFP:
1666a5c72737SRavi Kumar 		return axgbe_phy_use_sfp_mode(pdata, mode);
1667a5c72737SRavi Kumar 	default:
1668a5c72737SRavi Kumar 		return false;
1669a5c72737SRavi Kumar 	}
1670a5c72737SRavi Kumar }
1671a5c72737SRavi Kumar 
1672a5c72737SRavi Kumar static int axgbe_phy_link_status(struct axgbe_port *pdata, int *an_restart)
1673a5c72737SRavi Kumar {
1674a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1675a5c72737SRavi Kumar 	unsigned int reg;
1676a5c72737SRavi Kumar 
1677a5c72737SRavi Kumar 	*an_restart = 0;
1678a5c72737SRavi Kumar 
1679a5c72737SRavi Kumar 	if (phy_data->port_mode == AXGBE_PORT_MODE_SFP) {
1680a5c72737SRavi Kumar 		/* Check SFP signals */
1681a5c72737SRavi Kumar 		axgbe_phy_sfp_detect(pdata);
1682a5c72737SRavi Kumar 
1683a5c72737SRavi Kumar 		if (phy_data->sfp_changed) {
1684a5c72737SRavi Kumar 			*an_restart = 1;
1685a5c72737SRavi Kumar 			return 0;
1686a5c72737SRavi Kumar 		}
1687a5c72737SRavi Kumar 
1688a5c72737SRavi Kumar 		if (phy_data->sfp_mod_absent || phy_data->sfp_rx_los)
1689a5c72737SRavi Kumar 			return 0;
1690a5c72737SRavi Kumar 	}
1691a5c72737SRavi Kumar 
1692a5c72737SRavi Kumar 	/* Link status is latched low, so read once to clear
1693a5c72737SRavi Kumar 	 * and then read again to get current state
1694a5c72737SRavi Kumar 	 */
1695a5c72737SRavi Kumar 	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
1696a5c72737SRavi Kumar 	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
1697a5c72737SRavi Kumar 	if (reg & MDIO_STAT1_LSTATUS)
1698a5c72737SRavi Kumar 		return 1;
1699a5c72737SRavi Kumar 
1700a5c72737SRavi Kumar 	/* No link, attempt a receiver reset cycle */
1701a5c72737SRavi Kumar 	if (phy_data->rrc_count++) {
1702a5c72737SRavi Kumar 		phy_data->rrc_count = 0;
1703a5c72737SRavi Kumar 		axgbe_phy_rrc(pdata);
1704a5c72737SRavi Kumar 	}
1705a5c72737SRavi Kumar 
1706a5c72737SRavi Kumar 	return 0;
1707a5c72737SRavi Kumar }
1708a5c72737SRavi Kumar 
17094ac7516bSRavi Kumar static void axgbe_phy_sfp_gpio_setup(struct axgbe_port *pdata)
17104ac7516bSRavi Kumar {
17114ac7516bSRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
17124ac7516bSRavi Kumar 
17134ac7516bSRavi Kumar 	phy_data->sfp_gpio_address = AXGBE_GPIO_ADDRESS_PCA9555 +
1714*a3ec01b4SVenkat Kumar Ande 		XP_GET_BITS(pdata->pp3, XP_PROP_3, GPIO_ADDR);
17154ac7516bSRavi Kumar 
1716*a3ec01b4SVenkat Kumar Ande 	phy_data->sfp_gpio_mask = XP_GET_BITS(pdata->pp3, XP_PROP_3, GPIO_MASK);
17174ac7516bSRavi Kumar 
1718*a3ec01b4SVenkat Kumar Ande 	phy_data->sfp_gpio_rx_los = XP_GET_BITS(pdata->pp3, XP_PROP_3,
17194ac7516bSRavi Kumar 						GPIO_RX_LOS);
1720*a3ec01b4SVenkat Kumar Ande 	phy_data->sfp_gpio_tx_fault = XP_GET_BITS(pdata->pp3, XP_PROP_3,
17214ac7516bSRavi Kumar 						  GPIO_TX_FAULT);
1722*a3ec01b4SVenkat Kumar Ande 	phy_data->sfp_gpio_mod_absent = XP_GET_BITS(pdata->pp3, XP_PROP_3,
17234ac7516bSRavi Kumar 						    GPIO_MOD_ABS);
1724*a3ec01b4SVenkat Kumar Ande 	phy_data->sfp_gpio_rate_select = XP_GET_BITS(pdata->pp3, XP_PROP_3,
17254ac7516bSRavi Kumar 						     GPIO_RATE_SELECT);
17264ac7516bSRavi Kumar }
17274ac7516bSRavi Kumar 
17284ac7516bSRavi Kumar static void axgbe_phy_sfp_comm_setup(struct axgbe_port *pdata)
17294ac7516bSRavi Kumar {
17304ac7516bSRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1731*a3ec01b4SVenkat Kumar Ande 	unsigned int mux_addr_hi, mux_addr_lo;
17324ac7516bSRavi Kumar 
1733*a3ec01b4SVenkat Kumar Ande 	mux_addr_hi = XP_GET_BITS(pdata->pp4, XP_PROP_4, MUX_ADDR_HI);
1734*a3ec01b4SVenkat Kumar Ande 	mux_addr_lo = XP_GET_BITS(pdata->pp4, XP_PROP_4, MUX_ADDR_LO);
17354ac7516bSRavi Kumar 	if (mux_addr_lo == AXGBE_SFP_DIRECT)
17364ac7516bSRavi Kumar 		return;
17374ac7516bSRavi Kumar 
17384ac7516bSRavi Kumar 	phy_data->sfp_comm = AXGBE_SFP_COMM_PCA9545;
17394ac7516bSRavi Kumar 	phy_data->sfp_mux_address = (mux_addr_hi << 2) + mux_addr_lo;
1740*a3ec01b4SVenkat Kumar Ande 	phy_data->sfp_mux_channel = XP_GET_BITS(pdata->pp4, XP_PROP_4, MUX_CHAN);
17414ac7516bSRavi Kumar }
17424ac7516bSRavi Kumar 
17434ac7516bSRavi Kumar static void axgbe_phy_sfp_setup(struct axgbe_port *pdata)
17444ac7516bSRavi Kumar {
17454ac7516bSRavi Kumar 	axgbe_phy_sfp_comm_setup(pdata);
17464ac7516bSRavi Kumar 	axgbe_phy_sfp_gpio_setup(pdata);
17474ac7516bSRavi Kumar }
17484ac7516bSRavi Kumar 
17494ac7516bSRavi Kumar static bool axgbe_phy_redrv_error(struct axgbe_phy_data *phy_data)
17504ac7516bSRavi Kumar {
17514ac7516bSRavi Kumar 	if (!phy_data->redrv)
17524ac7516bSRavi Kumar 		return false;
17534ac7516bSRavi Kumar 
17544ac7516bSRavi Kumar 	if (phy_data->redrv_if >= AXGBE_PHY_REDRV_IF_MAX)
17554ac7516bSRavi Kumar 		return true;
17564ac7516bSRavi Kumar 
17574ac7516bSRavi Kumar 	switch (phy_data->redrv_model) {
17584ac7516bSRavi Kumar 	case AXGBE_PHY_REDRV_MODEL_4223:
17594ac7516bSRavi Kumar 		if (phy_data->redrv_lane > 3)
17604ac7516bSRavi Kumar 			return true;
17614ac7516bSRavi Kumar 		break;
17624ac7516bSRavi Kumar 	case AXGBE_PHY_REDRV_MODEL_4227:
17634ac7516bSRavi Kumar 		if (phy_data->redrv_lane > 1)
17644ac7516bSRavi Kumar 			return true;
17654ac7516bSRavi Kumar 		break;
17664ac7516bSRavi Kumar 	default:
17674ac7516bSRavi Kumar 		return true;
17684ac7516bSRavi Kumar 	}
17694ac7516bSRavi Kumar 
17704ac7516bSRavi Kumar 	return false;
17714ac7516bSRavi Kumar }
17724ac7516bSRavi Kumar 
17734ac7516bSRavi Kumar static int axgbe_phy_mdio_reset_setup(struct axgbe_port *pdata)
17744ac7516bSRavi Kumar {
17754ac7516bSRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
17764ac7516bSRavi Kumar 
17774ac7516bSRavi Kumar 	if (phy_data->conn_type != AXGBE_CONN_TYPE_MDIO)
17784ac7516bSRavi Kumar 		return 0;
1779*a3ec01b4SVenkat Kumar Ande 
1780*a3ec01b4SVenkat Kumar Ande 	phy_data->mdio_reset = XP_GET_BITS(pdata->pp3, XP_PROP_3, MDIO_RESET);
17814ac7516bSRavi Kumar 	switch (phy_data->mdio_reset) {
17824ac7516bSRavi Kumar 	case AXGBE_MDIO_RESET_NONE:
17834ac7516bSRavi Kumar 	case AXGBE_MDIO_RESET_I2C_GPIO:
17844ac7516bSRavi Kumar 	case AXGBE_MDIO_RESET_INT_GPIO:
17854ac7516bSRavi Kumar 		break;
17864ac7516bSRavi Kumar 	default:
17874ac7516bSRavi Kumar 		PMD_DRV_LOG(ERR, "unsupported MDIO reset (%#x)\n",
17884ac7516bSRavi Kumar 			    phy_data->mdio_reset);
17894ac7516bSRavi Kumar 		return -EINVAL;
17904ac7516bSRavi Kumar 	}
17914ac7516bSRavi Kumar 	if (phy_data->mdio_reset == AXGBE_MDIO_RESET_I2C_GPIO) {
17924ac7516bSRavi Kumar 		phy_data->mdio_reset_addr = AXGBE_GPIO_ADDRESS_PCA9555 +
1793*a3ec01b4SVenkat Kumar Ande 			XP_GET_BITS(pdata->pp3, XP_PROP_3,
17944ac7516bSRavi Kumar 				    MDIO_RESET_I2C_ADDR);
1795*a3ec01b4SVenkat Kumar Ande 		phy_data->mdio_reset_gpio = XP_GET_BITS(pdata->pp3, XP_PROP_3,
17964ac7516bSRavi Kumar 							MDIO_RESET_I2C_GPIO);
17974ac7516bSRavi Kumar 	} else if (phy_data->mdio_reset == AXGBE_MDIO_RESET_INT_GPIO) {
1798*a3ec01b4SVenkat Kumar Ande 		phy_data->mdio_reset_gpio = XP_GET_BITS(pdata->pp3, XP_PROP_3,
17994ac7516bSRavi Kumar 							MDIO_RESET_INT_GPIO);
18004ac7516bSRavi Kumar 	}
18014ac7516bSRavi Kumar 
18024ac7516bSRavi Kumar 	return 0;
18034ac7516bSRavi Kumar }
18044ac7516bSRavi Kumar 
18054ac7516bSRavi Kumar static bool axgbe_phy_port_mode_mismatch(struct axgbe_port *pdata)
18064ac7516bSRavi Kumar {
18074ac7516bSRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
18084ac7516bSRavi Kumar 
18094ac7516bSRavi Kumar 	switch (phy_data->port_mode) {
18104ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE:
1811443ab5aaSSelwin Sebastian 	case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG:
18124ac7516bSRavi Kumar 		if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) ||
18134ac7516bSRavi Kumar 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000))
18144ac7516bSRavi Kumar 			return false;
18154ac7516bSRavi Kumar 		break;
18164ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE_2500:
18174ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500)
18184ac7516bSRavi Kumar 			return false;
18194ac7516bSRavi Kumar 		break;
18204ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_T:
18214ac7516bSRavi Kumar 		if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) ||
18224ac7516bSRavi Kumar 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000))
18234ac7516bSRavi Kumar 			return false;
18244ac7516bSRavi Kumar 		break;
18254ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_X:
18264ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000)
18274ac7516bSRavi Kumar 			return false;
18284ac7516bSRavi Kumar 		break;
18294ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_NBASE_T:
18304ac7516bSRavi Kumar 		if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) ||
18314ac7516bSRavi Kumar 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) ||
18324ac7516bSRavi Kumar 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500))
18334ac7516bSRavi Kumar 			return false;
18344ac7516bSRavi Kumar 		break;
18354ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_T:
18364ac7516bSRavi Kumar 		if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) ||
18374ac7516bSRavi Kumar 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) ||
18384ac7516bSRavi Kumar 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000))
18394ac7516bSRavi Kumar 			return false;
18404ac7516bSRavi Kumar 		break;
18414ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_R:
18424ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000)
18434ac7516bSRavi Kumar 			return false;
18444ac7516bSRavi Kumar 		break;
18454ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_SFP:
18464ac7516bSRavi Kumar 		if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) ||
18474ac7516bSRavi Kumar 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) ||
18484ac7516bSRavi Kumar 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000))
18494ac7516bSRavi Kumar 			return false;
18504ac7516bSRavi Kumar 		break;
18514ac7516bSRavi Kumar 	default:
18524ac7516bSRavi Kumar 		break;
18534ac7516bSRavi Kumar 	}
18544ac7516bSRavi Kumar 
18554ac7516bSRavi Kumar 	return true;
18564ac7516bSRavi Kumar }
18574ac7516bSRavi Kumar 
18584ac7516bSRavi Kumar static bool axgbe_phy_conn_type_mismatch(struct axgbe_port *pdata)
18594ac7516bSRavi Kumar {
18604ac7516bSRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
18614ac7516bSRavi Kumar 
18624ac7516bSRavi Kumar 	switch (phy_data->port_mode) {
18634ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE:
1864443ab5aaSSelwin Sebastian 	case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG:
18654ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE_2500:
18664ac7516bSRavi Kumar 		if (phy_data->conn_type == AXGBE_CONN_TYPE_BACKPLANE)
18674ac7516bSRavi Kumar 			return false;
18684ac7516bSRavi Kumar 		break;
18694ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_T:
18704ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_X:
18714ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_NBASE_T:
18724ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_T:
18734ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_R:
18744ac7516bSRavi Kumar 		if (phy_data->conn_type == AXGBE_CONN_TYPE_MDIO)
18754ac7516bSRavi Kumar 			return false;
18764ac7516bSRavi Kumar 		break;
18774ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_SFP:
18784ac7516bSRavi Kumar 		if (phy_data->conn_type == AXGBE_CONN_TYPE_SFP)
18794ac7516bSRavi Kumar 			return false;
18804ac7516bSRavi Kumar 		break;
18814ac7516bSRavi Kumar 	default:
18824ac7516bSRavi Kumar 		break;
18834ac7516bSRavi Kumar 	}
18844ac7516bSRavi Kumar 
18854ac7516bSRavi Kumar 	return true;
18864ac7516bSRavi Kumar }
18874ac7516bSRavi Kumar 
18884ac7516bSRavi Kumar static bool axgbe_phy_port_enabled(struct axgbe_port *pdata)
18894ac7516bSRavi Kumar {
1890*a3ec01b4SVenkat Kumar Ande 	if (!XP_GET_BITS(pdata->pp0, XP_PROP_0, PORT_SPEEDS))
18914ac7516bSRavi Kumar 		return false;
1892*a3ec01b4SVenkat Kumar Ande 	if (!XP_GET_BITS(pdata->pp0, XP_PROP_0, CONN_TYPE))
18934ac7516bSRavi Kumar 		return false;
18944ac7516bSRavi Kumar 
18954ac7516bSRavi Kumar 	return true;
18964ac7516bSRavi Kumar }
18974ac7516bSRavi Kumar 
189800072056SRavi Kumar static void axgbe_phy_cdr_track(struct axgbe_port *pdata)
189900072056SRavi Kumar {
190000072056SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
190100072056SRavi Kumar 
190200072056SRavi Kumar 	if (!pdata->vdata->an_cdr_workaround)
190300072056SRavi Kumar 		return;
190400072056SRavi Kumar 
190500072056SRavi Kumar 	if (!phy_data->phy_cdr_notrack)
190600072056SRavi Kumar 		return;
190700072056SRavi Kumar 
190800072056SRavi Kumar 	rte_delay_us(phy_data->phy_cdr_delay + 400);
190900072056SRavi Kumar 
191000072056SRavi Kumar 	XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_CDR_CONTROL,
191100072056SRavi Kumar 			 AXGBE_PMA_CDR_TRACK_EN_MASK,
191200072056SRavi Kumar 			 AXGBE_PMA_CDR_TRACK_EN_ON);
191300072056SRavi Kumar 
191400072056SRavi Kumar 	phy_data->phy_cdr_notrack = 0;
191500072056SRavi Kumar }
191600072056SRavi Kumar 
191700072056SRavi Kumar static void axgbe_phy_cdr_notrack(struct axgbe_port *pdata)
191800072056SRavi Kumar {
191900072056SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
192000072056SRavi Kumar 
192100072056SRavi Kumar 	if (!pdata->vdata->an_cdr_workaround)
192200072056SRavi Kumar 		return;
192300072056SRavi Kumar 
192400072056SRavi Kumar 	if (phy_data->phy_cdr_notrack)
192500072056SRavi Kumar 		return;
192600072056SRavi Kumar 
192700072056SRavi Kumar 	XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_CDR_CONTROL,
192800072056SRavi Kumar 			 AXGBE_PMA_CDR_TRACK_EN_MASK,
192900072056SRavi Kumar 			 AXGBE_PMA_CDR_TRACK_EN_OFF);
193000072056SRavi Kumar 
193100072056SRavi Kumar 	axgbe_phy_rrc(pdata);
193200072056SRavi Kumar 
193300072056SRavi Kumar 	phy_data->phy_cdr_notrack = 1;
193400072056SRavi Kumar }
193500072056SRavi Kumar 
193600072056SRavi Kumar static void axgbe_phy_kr_training_post(struct axgbe_port *pdata)
193700072056SRavi Kumar {
193800072056SRavi Kumar 	if (!pdata->cdr_track_early)
193900072056SRavi Kumar 		axgbe_phy_cdr_track(pdata);
194000072056SRavi Kumar }
194100072056SRavi Kumar 
194200072056SRavi Kumar static void axgbe_phy_kr_training_pre(struct axgbe_port *pdata)
194300072056SRavi Kumar {
194400072056SRavi Kumar 	if (pdata->cdr_track_early)
194500072056SRavi Kumar 		axgbe_phy_cdr_track(pdata);
194600072056SRavi Kumar }
194700072056SRavi Kumar 
194800072056SRavi Kumar static void axgbe_phy_an_post(struct axgbe_port *pdata)
194900072056SRavi Kumar {
195000072056SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
195100072056SRavi Kumar 
195200072056SRavi Kumar 	switch (pdata->an_mode) {
195300072056SRavi Kumar 	case AXGBE_AN_MODE_CL73:
195400072056SRavi Kumar 	case AXGBE_AN_MODE_CL73_REDRV:
195500072056SRavi Kumar 		if (phy_data->cur_mode != AXGBE_MODE_KR)
195600072056SRavi Kumar 			break;
195700072056SRavi Kumar 
195800072056SRavi Kumar 		axgbe_phy_cdr_track(pdata);
195900072056SRavi Kumar 
196000072056SRavi Kumar 		switch (pdata->an_result) {
196100072056SRavi Kumar 		case AXGBE_AN_READY:
196200072056SRavi Kumar 		case AXGBE_AN_COMPLETE:
196300072056SRavi Kumar 			break;
196400072056SRavi Kumar 		default:
196500072056SRavi Kumar 			if (phy_data->phy_cdr_delay < AXGBE_CDR_DELAY_MAX)
196600072056SRavi Kumar 				phy_data->phy_cdr_delay += AXGBE_CDR_DELAY_INC;
196700072056SRavi Kumar 			break;
196800072056SRavi Kumar 		}
196900072056SRavi Kumar 		break;
197000072056SRavi Kumar 	default:
197100072056SRavi Kumar 		break;
197200072056SRavi Kumar 	}
197300072056SRavi Kumar }
197400072056SRavi Kumar 
197500072056SRavi Kumar static void axgbe_phy_an_pre(struct axgbe_port *pdata)
197600072056SRavi Kumar {
197700072056SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
197800072056SRavi Kumar 
197900072056SRavi Kumar 	switch (pdata->an_mode) {
198000072056SRavi Kumar 	case AXGBE_AN_MODE_CL73:
198100072056SRavi Kumar 	case AXGBE_AN_MODE_CL73_REDRV:
198200072056SRavi Kumar 		if (phy_data->cur_mode != AXGBE_MODE_KR)
198300072056SRavi Kumar 			break;
198400072056SRavi Kumar 
198500072056SRavi Kumar 		axgbe_phy_cdr_notrack(pdata);
198600072056SRavi Kumar 		break;
198700072056SRavi Kumar 	default:
198800072056SRavi Kumar 		break;
198900072056SRavi Kumar 	}
199000072056SRavi Kumar }
199100072056SRavi Kumar 
1992a5c72737SRavi Kumar static void axgbe_phy_stop(struct axgbe_port *pdata)
1993a5c72737SRavi Kumar {
1994a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1995a5c72737SRavi Kumar 
1996a5c72737SRavi Kumar 	/* Reset SFP data */
1997a5c72737SRavi Kumar 	axgbe_phy_sfp_reset(phy_data);
1998a5c72737SRavi Kumar 	axgbe_phy_sfp_mod_absent(pdata);
1999a5c72737SRavi Kumar 
200000072056SRavi Kumar 	/* Reset CDR support */
200100072056SRavi Kumar 	axgbe_phy_cdr_track(pdata);
200200072056SRavi Kumar 
2003a5c72737SRavi Kumar 	/* Power off the PHY */
2004a5c72737SRavi Kumar 	axgbe_phy_power_off(pdata);
2005a5c72737SRavi Kumar 
2006a5c72737SRavi Kumar 	/* Stop the I2C controller */
2007a5c72737SRavi Kumar 	pdata->i2c_if.i2c_stop(pdata);
2008a5c72737SRavi Kumar }
2009a5c72737SRavi Kumar 
2010a5c72737SRavi Kumar static int axgbe_phy_start(struct axgbe_port *pdata)
2011a5c72737SRavi Kumar {
2012a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
2013a5c72737SRavi Kumar 	int ret;
2014a5c72737SRavi Kumar 
2015a5c72737SRavi Kumar 	/* Start the I2C controller */
2016a5c72737SRavi Kumar 	ret = pdata->i2c_if.i2c_start(pdata);
2017a5c72737SRavi Kumar 	if (ret)
2018a5c72737SRavi Kumar 		return ret;
2019a5c72737SRavi Kumar 
2020a5c72737SRavi Kumar 	/* Start in highest supported mode */
2021a5c72737SRavi Kumar 	axgbe_phy_set_mode(pdata, phy_data->start_mode);
2022a5c72737SRavi Kumar 
202300072056SRavi Kumar 	/* Reset CDR support */
202400072056SRavi Kumar 	axgbe_phy_cdr_track(pdata);
202500072056SRavi Kumar 
2026a5c72737SRavi Kumar 	/* After starting the I2C controller, we can check for an SFP */
2027a5c72737SRavi Kumar 	switch (phy_data->port_mode) {
2028a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_SFP:
2029a5c72737SRavi Kumar 		axgbe_phy_sfp_detect(pdata);
2030a5c72737SRavi Kumar 		break;
2031a5c72737SRavi Kumar 	default:
2032a5c72737SRavi Kumar 		break;
2033a5c72737SRavi Kumar 	}
2034102b6ec3SGirish Nandibasappa 	pdata->phy.advertising &= axgbe_phy_an_advertising(pdata);
2035a5c72737SRavi Kumar 
2036a5c72737SRavi Kumar 	return ret;
2037a5c72737SRavi Kumar }
2038a5c72737SRavi Kumar 
2039a5c72737SRavi Kumar static int axgbe_phy_reset(struct axgbe_port *pdata)
2040a5c72737SRavi Kumar {
2041a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
2042a5c72737SRavi Kumar 	enum axgbe_mode cur_mode;
2043a5c72737SRavi Kumar 
2044a5c72737SRavi Kumar 	/* Reset by power cycling the PHY */
2045a5c72737SRavi Kumar 	cur_mode = phy_data->cur_mode;
2046a5c72737SRavi Kumar 	axgbe_phy_power_off(pdata);
2047a5c72737SRavi Kumar 	/* First time reset is done with passed unknown mode*/
2048a5c72737SRavi Kumar 	axgbe_phy_set_mode(pdata, cur_mode);
2049a5c72737SRavi Kumar 	return 0;
2050a5c72737SRavi Kumar }
2051a5c72737SRavi Kumar 
20524ac7516bSRavi Kumar static int axgbe_phy_init(struct axgbe_port *pdata)
20534ac7516bSRavi Kumar {
20544ac7516bSRavi Kumar 	struct axgbe_phy_data *phy_data;
20554ac7516bSRavi Kumar 	int ret;
20564ac7516bSRavi Kumar 
20574ac7516bSRavi Kumar 	/* Check if enabled */
20584ac7516bSRavi Kumar 	if (!axgbe_phy_port_enabled(pdata)) {
20594ac7516bSRavi Kumar 		PMD_DRV_LOG(ERR, "device is not enabled\n");
20604ac7516bSRavi Kumar 		return -ENODEV;
20614ac7516bSRavi Kumar 	}
20624ac7516bSRavi Kumar 
20634ac7516bSRavi Kumar 	/* Initialize the I2C controller */
20644ac7516bSRavi Kumar 	ret = pdata->i2c_if.i2c_init(pdata);
20654ac7516bSRavi Kumar 	if (ret)
20664ac7516bSRavi Kumar 		return ret;
20674ac7516bSRavi Kumar 
20684ac7516bSRavi Kumar 	phy_data = rte_zmalloc("phy_data memory", sizeof(*phy_data), 0);
20694ac7516bSRavi Kumar 	if (!phy_data) {
20704ac7516bSRavi Kumar 		PMD_DRV_LOG(ERR, "phy_data allocation failed\n");
20714ac7516bSRavi Kumar 		return -ENOMEM;
20724ac7516bSRavi Kumar 	}
20734ac7516bSRavi Kumar 	pdata->phy_data = phy_data;
20744ac7516bSRavi Kumar 
2075*a3ec01b4SVenkat Kumar Ande 	phy_data->port_mode = XP_GET_BITS(pdata->pp0, XP_PROP_0, PORT_MODE);
2076*a3ec01b4SVenkat Kumar Ande 	phy_data->port_id = XP_GET_BITS(pdata->pp0, XP_PROP_0, PORT_ID);
2077*a3ec01b4SVenkat Kumar Ande 	phy_data->port_speeds = XP_GET_BITS(pdata->pp0, XP_PROP_0, PORT_SPEEDS);
2078*a3ec01b4SVenkat Kumar Ande 	phy_data->conn_type = XP_GET_BITS(pdata->pp0, XP_PROP_0, CONN_TYPE);
2079*a3ec01b4SVenkat Kumar Ande 	phy_data->mdio_addr = XP_GET_BITS(pdata->pp0, XP_PROP_0, MDIO_ADDR);
20804ac7516bSRavi Kumar 
2081*a3ec01b4SVenkat Kumar Ande 	phy_data->redrv = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_PRESENT);
2082*a3ec01b4SVenkat Kumar Ande 	phy_data->redrv_if = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_IF);
2083*a3ec01b4SVenkat Kumar Ande 	phy_data->redrv_addr = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_ADDR);
2084*a3ec01b4SVenkat Kumar Ande 	phy_data->redrv_lane = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_LANE);
2085*a3ec01b4SVenkat Kumar Ande 	phy_data->redrv_model = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_MODEL);
20864ac7516bSRavi Kumar 
20874ac7516bSRavi Kumar 	/* Validate the connection requested */
20884ac7516bSRavi Kumar 	if (axgbe_phy_conn_type_mismatch(pdata)) {
20894ac7516bSRavi Kumar 		PMD_DRV_LOG(ERR, "phy mode/connection mismatch (%#x/%#x)\n",
20904ac7516bSRavi Kumar 			    phy_data->port_mode, phy_data->conn_type);
20914ac7516bSRavi Kumar 		return -EINVAL;
20924ac7516bSRavi Kumar 	}
20934ac7516bSRavi Kumar 
20944ac7516bSRavi Kumar 	/* Validate the mode requested */
20954ac7516bSRavi Kumar 	if (axgbe_phy_port_mode_mismatch(pdata)) {
20964ac7516bSRavi Kumar 		PMD_DRV_LOG(ERR, "phy mode/speed mismatch (%#x/%#x)\n",
20974ac7516bSRavi Kumar 			    phy_data->port_mode, phy_data->port_speeds);
20984ac7516bSRavi Kumar 		return -EINVAL;
20994ac7516bSRavi Kumar 	}
21004ac7516bSRavi Kumar 
21014ac7516bSRavi Kumar 	/* Check for and validate MDIO reset support */
21024ac7516bSRavi Kumar 	ret = axgbe_phy_mdio_reset_setup(pdata);
21034ac7516bSRavi Kumar 	if (ret)
21044ac7516bSRavi Kumar 		return ret;
21054ac7516bSRavi Kumar 
21064ac7516bSRavi Kumar 	/* Validate the re-driver information */
21074ac7516bSRavi Kumar 	if (axgbe_phy_redrv_error(phy_data)) {
21084ac7516bSRavi Kumar 		PMD_DRV_LOG(ERR, "phy re-driver settings error\n");
21094ac7516bSRavi Kumar 		return -EINVAL;
21104ac7516bSRavi Kumar 	}
21114ac7516bSRavi Kumar 	pdata->kr_redrv = phy_data->redrv;
21124ac7516bSRavi Kumar 
21134ac7516bSRavi Kumar 	/* Indicate current mode is unknown */
21144ac7516bSRavi Kumar 	phy_data->cur_mode = AXGBE_MODE_UNKNOWN;
21154ac7516bSRavi Kumar 
21164ac7516bSRavi Kumar 	/* Initialize supported features */
21174ac7516bSRavi Kumar 	pdata->phy.supported = 0;
21184ac7516bSRavi Kumar 
21194ac7516bSRavi Kumar 	switch (phy_data->port_mode) {
21204ac7516bSRavi Kumar 		/* Backplane support */
21214ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE:
21224ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Autoneg;
2123443ab5aaSSelwin Sebastian 		/* Fallthrough */
2124443ab5aaSSelwin Sebastian 	case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG:
21254ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
21264ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Backplane;
21274ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) {
21284ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_1000baseKX_Full;
21294ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_KX_1000;
21304ac7516bSRavi Kumar 		}
21314ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) {
21324ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_10000baseKR_Full;
21334ac7516bSRavi Kumar 			if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
21344ac7516bSRavi Kumar 				pdata->phy.supported |=
21354ac7516bSRavi Kumar 					SUPPORTED_10000baseR_FEC;
21364ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_KR;
21374ac7516bSRavi Kumar 		}
21384ac7516bSRavi Kumar 
21394ac7516bSRavi Kumar 		phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE;
21404ac7516bSRavi Kumar 		break;
21414ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE_2500:
21424ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
21434ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Backplane;
21444ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_2500baseX_Full;
21454ac7516bSRavi Kumar 		phy_data->start_mode = AXGBE_MODE_KX_2500;
21464ac7516bSRavi Kumar 
21474ac7516bSRavi Kumar 		phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE;
21484ac7516bSRavi Kumar 		break;
21494ac7516bSRavi Kumar 
21504ac7516bSRavi Kumar 		/* MDIO 1GBase-T support */
21514ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_T:
21524ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Autoneg;
21534ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
21544ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_TP;
21554ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) {
21564ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_100baseT_Full;
21574ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_SGMII_100;
21584ac7516bSRavi Kumar 		}
21594ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) {
21604ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_1000baseT_Full;
21614ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_SGMII_1000;
21624ac7516bSRavi Kumar 		}
21634ac7516bSRavi Kumar 
21644ac7516bSRavi Kumar 		phy_data->phydev_mode = AXGBE_MDIO_MODE_CL22;
21654ac7516bSRavi Kumar 		break;
21664ac7516bSRavi Kumar 
21674ac7516bSRavi Kumar 		/* MDIO Base-X support */
21684ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_X:
21694ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Autoneg;
21704ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
21714ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_FIBRE;
21724ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_1000baseT_Full;
21734ac7516bSRavi Kumar 		phy_data->start_mode = AXGBE_MODE_X;
21744ac7516bSRavi Kumar 
21754ac7516bSRavi Kumar 		phy_data->phydev_mode = AXGBE_MDIO_MODE_CL22;
21764ac7516bSRavi Kumar 		break;
21774ac7516bSRavi Kumar 
21784ac7516bSRavi Kumar 		/* MDIO NBase-T support */
21794ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_NBASE_T:
21804ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Autoneg;
21814ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
21824ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_TP;
21834ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) {
21844ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_100baseT_Full;
21854ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_SGMII_100;
21864ac7516bSRavi Kumar 		}
21874ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) {
21884ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_1000baseT_Full;
21894ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_SGMII_1000;
21904ac7516bSRavi Kumar 		}
21914ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500) {
21924ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_2500baseX_Full;
21934ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_KX_2500;
21944ac7516bSRavi Kumar 		}
21954ac7516bSRavi Kumar 
21964ac7516bSRavi Kumar 		phy_data->phydev_mode = AXGBE_MDIO_MODE_CL45;
21974ac7516bSRavi Kumar 		break;
21984ac7516bSRavi Kumar 
21994ac7516bSRavi Kumar 		/* 10GBase-T support */
22004ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_T:
22014ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Autoneg;
22024ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
22034ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_TP;
22044ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) {
22054ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_100baseT_Full;
22064ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_SGMII_100;
22074ac7516bSRavi Kumar 		}
22084ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) {
22094ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_1000baseT_Full;
22104ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_SGMII_1000;
22114ac7516bSRavi Kumar 		}
22124ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) {
22134ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_10000baseT_Full;
22144ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_KR;
22154ac7516bSRavi Kumar 		}
22164ac7516bSRavi Kumar 
22174ac7516bSRavi Kumar 		phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE;
22184ac7516bSRavi Kumar 		break;
22194ac7516bSRavi Kumar 
22204ac7516bSRavi Kumar 		/* 10GBase-R support */
22214ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_R:
22224ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Autoneg;
22234ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
22244ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_TP;
22254ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_10000baseT_Full;
22264ac7516bSRavi Kumar 		if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
22274ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_10000baseR_FEC;
22284ac7516bSRavi Kumar 		phy_data->start_mode = AXGBE_MODE_SFI;
22294ac7516bSRavi Kumar 
22304ac7516bSRavi Kumar 		phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE;
22314ac7516bSRavi Kumar 		break;
22324ac7516bSRavi Kumar 
22334ac7516bSRavi Kumar 		/* SFP support */
22344ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_SFP:
22354ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Autoneg;
22364ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
22374ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_TP;
22384ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_FIBRE;
22394ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) {
22404ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_100baseT_Full;
22414ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_SGMII_100;
22424ac7516bSRavi Kumar 		}
22434ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) {
22444ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_1000baseT_Full;
22454ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_SGMII_1000;
22464ac7516bSRavi Kumar 		}
22474ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) {
22484ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_10000baseT_Full;
22494ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_SFI;
22504ac7516bSRavi Kumar 			if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
22514ac7516bSRavi Kumar 				pdata->phy.supported |=
22524ac7516bSRavi Kumar 					SUPPORTED_10000baseR_FEC;
22534ac7516bSRavi Kumar 		}
22544ac7516bSRavi Kumar 
22554ac7516bSRavi Kumar 		phy_data->phydev_mode = AXGBE_MDIO_MODE_CL22;
22564ac7516bSRavi Kumar 
22574ac7516bSRavi Kumar 		axgbe_phy_sfp_setup(pdata);
22584ac7516bSRavi Kumar 		break;
22594ac7516bSRavi Kumar 	default:
22604ac7516bSRavi Kumar 		return -EINVAL;
22614ac7516bSRavi Kumar 	}
22624ac7516bSRavi Kumar 
22634ac7516bSRavi Kumar 	if ((phy_data->conn_type & AXGBE_CONN_TYPE_MDIO) &&
22644ac7516bSRavi Kumar 	    (phy_data->phydev_mode != AXGBE_MDIO_MODE_NONE)) {
22654ac7516bSRavi Kumar 		ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->mdio_addr,
22664ac7516bSRavi Kumar 						    phy_data->phydev_mode);
22674ac7516bSRavi Kumar 		if (ret) {
22684ac7516bSRavi Kumar 			PMD_DRV_LOG(ERR, "mdio port/clause not compatible (%d/%u)\n",
22694ac7516bSRavi Kumar 				    phy_data->mdio_addr, phy_data->phydev_mode);
22704ac7516bSRavi Kumar 			return -EINVAL;
22714ac7516bSRavi Kumar 		}
22724ac7516bSRavi Kumar 	}
22734ac7516bSRavi Kumar 
22744ac7516bSRavi Kumar 	if (phy_data->redrv && !phy_data->redrv_if) {
22754ac7516bSRavi Kumar 		ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->redrv_addr,
22764ac7516bSRavi Kumar 						    AXGBE_MDIO_MODE_CL22);
22774ac7516bSRavi Kumar 		if (ret) {
22784ac7516bSRavi Kumar 			PMD_DRV_LOG(ERR, "redriver mdio port not compatible (%u)\n",
22794ac7516bSRavi Kumar 				    phy_data->redrv_addr);
22804ac7516bSRavi Kumar 			return -EINVAL;
22814ac7516bSRavi Kumar 		}
22824ac7516bSRavi Kumar 	}
228300072056SRavi Kumar 
228400072056SRavi Kumar 	phy_data->phy_cdr_delay = AXGBE_CDR_DELAY_INIT;
22854ac7516bSRavi Kumar 	return 0;
22864ac7516bSRavi Kumar }
22874ac7516bSRavi Kumar void axgbe_init_function_ptrs_phy_v2(struct axgbe_phy_if *phy_if)
22884ac7516bSRavi Kumar {
22894ac7516bSRavi Kumar 	struct axgbe_phy_impl_if *phy_impl = &phy_if->phy_impl;
22904ac7516bSRavi Kumar 
22914ac7516bSRavi Kumar 	phy_impl->init			= axgbe_phy_init;
2292a5c72737SRavi Kumar 	phy_impl->reset			= axgbe_phy_reset;
2293a5c72737SRavi Kumar 	phy_impl->start			= axgbe_phy_start;
2294a5c72737SRavi Kumar 	phy_impl->stop			= axgbe_phy_stop;
2295a5c72737SRavi Kumar 	phy_impl->link_status		= axgbe_phy_link_status;
2296a5c72737SRavi Kumar 	phy_impl->use_mode		= axgbe_phy_use_mode;
2297a5c72737SRavi Kumar 	phy_impl->set_mode		= axgbe_phy_set_mode;
2298a5c72737SRavi Kumar 	phy_impl->get_mode		= axgbe_phy_get_mode;
2299a5c72737SRavi Kumar 	phy_impl->switch_mode		= axgbe_phy_switch_mode;
2300a5c72737SRavi Kumar 	phy_impl->cur_mode		= axgbe_phy_cur_mode;
2301a5c72737SRavi Kumar 	phy_impl->an_mode		= axgbe_phy_an_mode;
2302a5c72737SRavi Kumar 	phy_impl->an_config		= axgbe_phy_an_config;
2303a5c72737SRavi Kumar 	phy_impl->an_advertising	= axgbe_phy_an_advertising;
2304a5c72737SRavi Kumar 	phy_impl->an_outcome		= axgbe_phy_an_outcome;
230500072056SRavi Kumar 
230600072056SRavi Kumar 	phy_impl->an_pre		= axgbe_phy_an_pre;
230700072056SRavi Kumar 	phy_impl->an_post		= axgbe_phy_an_post;
230800072056SRavi Kumar 
230900072056SRavi Kumar 	phy_impl->kr_training_pre	= axgbe_phy_kr_training_pre;
231000072056SRavi Kumar 	phy_impl->kr_training_post	= axgbe_phy_kr_training_post;
23114ac7516bSRavi Kumar }
2312