xref: /dpdk/drivers/net/axgbe/axgbe_phy_impl.c (revision e99981af34632ecce3bac82d05db97b08308f9b5)
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 
101f9d2d3aSVenkat Kumar Ande #define AXGBE_PHY_PORT_SPEED_10		BIT(0)
11a935a4c3SSelwin Sebastian #define AXGBE_PHY_PORT_SPEED_100	BIT(1)
12a935a4c3SSelwin Sebastian #define AXGBE_PHY_PORT_SPEED_1000	BIT(2)
13a935a4c3SSelwin Sebastian #define AXGBE_PHY_PORT_SPEED_2500	BIT(3)
14a935a4c3SSelwin Sebastian #define AXGBE_PHY_PORT_SPEED_10000	BIT(4)
154ac7516bSRavi Kumar 
164ac7516bSRavi Kumar #define AXGBE_MUTEX_RELEASE		0x80000000
174ac7516bSRavi Kumar 
184ac7516bSRavi Kumar #define AXGBE_SFP_DIRECT		7
194ac7516bSRavi Kumar 
204ac7516bSRavi Kumar /* I2C target addresses */
214ac7516bSRavi Kumar #define AXGBE_SFP_SERIAL_ID_ADDRESS	0x50
224ac7516bSRavi Kumar #define AXGBE_SFP_DIAG_INFO_ADDRESS	0x51
234ac7516bSRavi Kumar #define AXGBE_SFP_PHY_ADDRESS		0x56
244ac7516bSRavi Kumar #define AXGBE_GPIO_ADDRESS_PCA9555	0x20
254ac7516bSRavi Kumar 
264ac7516bSRavi Kumar /* SFP sideband signal indicators */
274ac7516bSRavi Kumar #define AXGBE_GPIO_NO_TX_FAULT		BIT(0)
284ac7516bSRavi Kumar #define AXGBE_GPIO_NO_RATE_SELECT	BIT(1)
294ac7516bSRavi Kumar #define AXGBE_GPIO_NO_MOD_ABSENT	BIT(2)
304ac7516bSRavi Kumar #define AXGBE_GPIO_NO_RX_LOS		BIT(3)
314ac7516bSRavi Kumar 
324ac7516bSRavi Kumar /* Rate-change complete wait/retry count */
334ac7516bSRavi Kumar #define AXGBE_RATECHANGE_COUNT		500
344ac7516bSRavi Kumar 
3500072056SRavi Kumar /* CDR delay values for KR support (in usec) */
3600072056SRavi Kumar #define AXGBE_CDR_DELAY_INIT		10000
3700072056SRavi Kumar #define AXGBE_CDR_DELAY_INC		10000
3800072056SRavi Kumar #define AXGBE_CDR_DELAY_MAX		100000
3900072056SRavi Kumar 
404ac7516bSRavi Kumar enum axgbe_port_mode {
414ac7516bSRavi Kumar 	AXGBE_PORT_MODE_RSVD = 0,
424ac7516bSRavi Kumar 	AXGBE_PORT_MODE_BACKPLANE,
434ac7516bSRavi Kumar 	AXGBE_PORT_MODE_BACKPLANE_2500,
444ac7516bSRavi Kumar 	AXGBE_PORT_MODE_1000BASE_T,
454ac7516bSRavi Kumar 	AXGBE_PORT_MODE_1000BASE_X,
464ac7516bSRavi Kumar 	AXGBE_PORT_MODE_NBASE_T,
474ac7516bSRavi Kumar 	AXGBE_PORT_MODE_10GBASE_T,
484ac7516bSRavi Kumar 	AXGBE_PORT_MODE_10GBASE_R,
494ac7516bSRavi Kumar 	AXGBE_PORT_MODE_SFP,
50443ab5aaSSelwin Sebastian 	AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG,
514ac7516bSRavi Kumar 	AXGBE_PORT_MODE_MAX,
524ac7516bSRavi Kumar };
534ac7516bSRavi Kumar 
544ac7516bSRavi Kumar enum axgbe_conn_type {
554ac7516bSRavi Kumar 	AXGBE_CONN_TYPE_NONE = 0,
564ac7516bSRavi Kumar 	AXGBE_CONN_TYPE_SFP,
574ac7516bSRavi Kumar 	AXGBE_CONN_TYPE_MDIO,
584ac7516bSRavi Kumar 	AXGBE_CONN_TYPE_RSVD1,
594ac7516bSRavi Kumar 	AXGBE_CONN_TYPE_BACKPLANE,
604ac7516bSRavi Kumar 	AXGBE_CONN_TYPE_MAX,
614ac7516bSRavi Kumar };
624ac7516bSRavi Kumar 
634ac7516bSRavi Kumar /* SFP/SFP+ related definitions */
644ac7516bSRavi Kumar enum axgbe_sfp_comm {
654ac7516bSRavi Kumar 	AXGBE_SFP_COMM_DIRECT = 0,
664ac7516bSRavi Kumar 	AXGBE_SFP_COMM_PCA9545,
674ac7516bSRavi Kumar };
684ac7516bSRavi Kumar 
694ac7516bSRavi Kumar enum axgbe_sfp_cable {
704ac7516bSRavi Kumar 	AXGBE_SFP_CABLE_UNKNOWN = 0,
714ac7516bSRavi Kumar 	AXGBE_SFP_CABLE_ACTIVE,
724ac7516bSRavi Kumar 	AXGBE_SFP_CABLE_PASSIVE,
734823ccdbSVenkat Kumar Ande 	AXGBE_SFP_CABLE_FIBER,
744ac7516bSRavi Kumar };
754ac7516bSRavi Kumar 
764ac7516bSRavi Kumar enum axgbe_sfp_base {
774ac7516bSRavi Kumar 	AXGBE_SFP_BASE_UNKNOWN = 0,
784ac7516bSRavi Kumar 	AXGBE_SFP_BASE_1000_T,
794ac7516bSRavi Kumar 	AXGBE_SFP_BASE_1000_SX,
804ac7516bSRavi Kumar 	AXGBE_SFP_BASE_1000_LX,
814ac7516bSRavi Kumar 	AXGBE_SFP_BASE_1000_CX,
824ac7516bSRavi Kumar 	AXGBE_SFP_BASE_10000_SR,
834ac7516bSRavi Kumar 	AXGBE_SFP_BASE_10000_LR,
844ac7516bSRavi Kumar 	AXGBE_SFP_BASE_10000_LRM,
854ac7516bSRavi Kumar 	AXGBE_SFP_BASE_10000_ER,
864ac7516bSRavi Kumar 	AXGBE_SFP_BASE_10000_CR,
874ac7516bSRavi Kumar };
884ac7516bSRavi Kumar 
894ac7516bSRavi Kumar enum axgbe_sfp_speed {
904ac7516bSRavi Kumar 	AXGBE_SFP_SPEED_UNKNOWN = 0,
914ac7516bSRavi Kumar 	AXGBE_SFP_SPEED_100_1000,
924ac7516bSRavi Kumar 	AXGBE_SFP_SPEED_1000,
934ac7516bSRavi Kumar 	AXGBE_SFP_SPEED_10000,
944ac7516bSRavi Kumar };
954ac7516bSRavi Kumar 
964ac7516bSRavi Kumar /* SFP Serial ID Base ID values relative to an offset of 0 */
974ac7516bSRavi Kumar #define AXGBE_SFP_BASE_ID			0
984ac7516bSRavi Kumar #define AXGBE_SFP_ID_SFP			0x03
994ac7516bSRavi Kumar 
1004ac7516bSRavi Kumar #define AXGBE_SFP_BASE_EXT_ID			1
1014ac7516bSRavi Kumar #define AXGBE_SFP_EXT_ID_SFP			0x04
1024ac7516bSRavi Kumar 
1034ac7516bSRavi Kumar #define AXGBE_SFP_BASE_10GBE_CC			3
1044ac7516bSRavi Kumar #define AXGBE_SFP_BASE_10GBE_CC_SR		BIT(4)
1054ac7516bSRavi Kumar #define AXGBE_SFP_BASE_10GBE_CC_LR		BIT(5)
1064ac7516bSRavi Kumar #define AXGBE_SFP_BASE_10GBE_CC_LRM		BIT(6)
1074ac7516bSRavi Kumar #define AXGBE_SFP_BASE_10GBE_CC_ER		BIT(7)
1084ac7516bSRavi Kumar 
1094ac7516bSRavi Kumar #define AXGBE_SFP_BASE_1GBE_CC			6
1104ac7516bSRavi Kumar #define AXGBE_SFP_BASE_1GBE_CC_SX		BIT(0)
1114ac7516bSRavi Kumar #define AXGBE_SFP_BASE_1GBE_CC_LX		BIT(1)
1124ac7516bSRavi Kumar #define AXGBE_SFP_BASE_1GBE_CC_CX		BIT(2)
1134ac7516bSRavi Kumar #define AXGBE_SFP_BASE_1GBE_CC_T		BIT(3)
1144ac7516bSRavi Kumar 
1154ac7516bSRavi Kumar #define AXGBE_SFP_BASE_CABLE			8
1164ac7516bSRavi Kumar #define AXGBE_SFP_BASE_CABLE_PASSIVE		BIT(2)
1174ac7516bSRavi Kumar #define AXGBE_SFP_BASE_CABLE_ACTIVE		BIT(3)
1184ac7516bSRavi Kumar 
1194ac7516bSRavi Kumar #define AXGBE_SFP_BASE_BR			12
1204ac7516bSRavi Kumar #define AXGBE_SFP_BASE_BR_1GBE_MIN		0x0a
1214ac7516bSRavi Kumar #define AXGBE_SFP_BASE_BR_10GBE_MIN		0x64
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 	/* SFP Support */
2094ac7516bSRavi Kumar 	enum axgbe_sfp_comm sfp_comm;
2104ac7516bSRavi Kumar 	unsigned int sfp_mux_address;
2114ac7516bSRavi Kumar 	unsigned int sfp_mux_channel;
2124ac7516bSRavi Kumar 
2134ac7516bSRavi Kumar 	unsigned int sfp_gpio_address;
2144ac7516bSRavi Kumar 	unsigned int sfp_gpio_mask;
2154ac7516bSRavi Kumar 	unsigned int sfp_gpio_rx_los;
2164ac7516bSRavi Kumar 	unsigned int sfp_gpio_tx_fault;
2174ac7516bSRavi Kumar 	unsigned int sfp_gpio_mod_absent;
2184ac7516bSRavi Kumar 	unsigned int sfp_gpio_rate_select;
2194ac7516bSRavi Kumar 
2204ac7516bSRavi Kumar 	unsigned int sfp_rx_los;
2214ac7516bSRavi Kumar 	unsigned int sfp_tx_fault;
2224ac7516bSRavi Kumar 	unsigned int sfp_mod_absent;
2234ac7516bSRavi Kumar 	unsigned int sfp_changed;
2244ac7516bSRavi Kumar 	unsigned int sfp_phy_avail;
2254ac7516bSRavi Kumar 	unsigned int sfp_cable_len;
2264ac7516bSRavi Kumar 	enum axgbe_sfp_base sfp_base;
2274ac7516bSRavi Kumar 	enum axgbe_sfp_cable sfp_cable;
2284ac7516bSRavi Kumar 	enum axgbe_sfp_speed sfp_speed;
2294ac7516bSRavi Kumar 	struct axgbe_sfp_eeprom sfp_eeprom;
2304ac7516bSRavi Kumar 
2314ac7516bSRavi Kumar 	/* External PHY support */
2324ac7516bSRavi Kumar 	enum axgbe_mdio_mode phydev_mode;
2334ac7516bSRavi Kumar 	enum axgbe_mdio_reset mdio_reset;
2344ac7516bSRavi Kumar 	unsigned int mdio_reset_addr;
2354ac7516bSRavi Kumar 	unsigned int mdio_reset_gpio;
2364ac7516bSRavi Kumar 
2374ac7516bSRavi Kumar 	/* Re-driver support */
2384ac7516bSRavi Kumar 	unsigned int redrv;
2394ac7516bSRavi Kumar 	unsigned int redrv_if;
2404ac7516bSRavi Kumar 	unsigned int redrv_addr;
2414ac7516bSRavi Kumar 	unsigned int redrv_lane;
2424ac7516bSRavi Kumar 	unsigned int redrv_model;
24300072056SRavi Kumar 
24400072056SRavi Kumar 	/* KR AN support */
24500072056SRavi Kumar 	unsigned int phy_cdr_notrack;
24600072056SRavi Kumar 	unsigned int phy_cdr_delay;
2474ac7516bSRavi Kumar };
2484ac7516bSRavi Kumar 
249a5c72737SRavi Kumar static enum axgbe_an_mode axgbe_phy_an_mode(struct axgbe_port *pdata);
2506c04898fSVenkat Kumar Ande static void axgbe_phy_perform_ratechange(struct axgbe_port *pdata,
2516c04898fSVenkat Kumar Ande 		enum axgbe_mb_cmd cmd, enum axgbe_mb_subcmd sub_cmd);
2526c04898fSVenkat Kumar Ande static void axgbe_phy_rrc(struct axgbe_port *pdata);
2536c04898fSVenkat Kumar Ande 
254a5c72737SRavi Kumar 
255a5c72737SRavi Kumar static int axgbe_phy_i2c_xfer(struct axgbe_port *pdata,
256a5c72737SRavi Kumar 			      struct axgbe_i2c_op *i2c_op)
257a5c72737SRavi Kumar {
258a5c72737SRavi Kumar 	return pdata->i2c_if.i2c_xfer(pdata, i2c_op);
259a5c72737SRavi Kumar }
260a5c72737SRavi Kumar 
261a5c72737SRavi Kumar static int axgbe_phy_redrv_write(struct axgbe_port *pdata, unsigned int reg,
262a5c72737SRavi Kumar 				 unsigned int val)
263a5c72737SRavi Kumar {
264a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
265a5c72737SRavi Kumar 	struct axgbe_i2c_op i2c_op;
266a5c72737SRavi Kumar 	uint16_t *redrv_val;
267a5c72737SRavi Kumar 	u8 redrv_data[5], csum;
268a5c72737SRavi Kumar 	unsigned int i, retry;
269a5c72737SRavi Kumar 	int ret;
270a5c72737SRavi Kumar 
271a5c72737SRavi Kumar 	/* High byte of register contains read/write indicator */
272a5c72737SRavi Kumar 	redrv_data[0] = ((reg >> 8) & 0xff) << 1;
273a5c72737SRavi Kumar 	redrv_data[1] = reg & 0xff;
274a5c72737SRavi Kumar 	redrv_val = (uint16_t *)&redrv_data[2];
275a5c72737SRavi Kumar 	*redrv_val = rte_cpu_to_be_16(val);
276a5c72737SRavi Kumar 
277a5c72737SRavi Kumar 	/* Calculate 1 byte checksum */
278a5c72737SRavi Kumar 	csum = 0;
279a5c72737SRavi Kumar 	for (i = 0; i < 4; i++) {
280a5c72737SRavi Kumar 		csum += redrv_data[i];
281a5c72737SRavi Kumar 		if (redrv_data[i] > csum)
282a5c72737SRavi Kumar 			csum++;
283a5c72737SRavi Kumar 	}
284a5c72737SRavi Kumar 	redrv_data[4] = ~csum;
285a5c72737SRavi Kumar 
286a5c72737SRavi Kumar 	retry = 1;
287a5c72737SRavi Kumar again1:
288a5c72737SRavi Kumar 	i2c_op.cmd = AXGBE_I2C_CMD_WRITE;
289a5c72737SRavi Kumar 	i2c_op.target = phy_data->redrv_addr;
290a5c72737SRavi Kumar 	i2c_op.len = sizeof(redrv_data);
291a5c72737SRavi Kumar 	i2c_op.buf = redrv_data;
292a5c72737SRavi Kumar 	ret = axgbe_phy_i2c_xfer(pdata, &i2c_op);
293a5c72737SRavi Kumar 	if (ret) {
294a5c72737SRavi Kumar 		if ((ret == -EAGAIN) && retry--)
295a5c72737SRavi Kumar 			goto again1;
296a5c72737SRavi Kumar 
297a5c72737SRavi Kumar 		return ret;
298a5c72737SRavi Kumar 	}
299a5c72737SRavi Kumar 
300a5c72737SRavi Kumar 	retry = 1;
301a5c72737SRavi Kumar again2:
302a5c72737SRavi Kumar 	i2c_op.cmd = AXGBE_I2C_CMD_READ;
303a5c72737SRavi Kumar 	i2c_op.target = phy_data->redrv_addr;
304a5c72737SRavi Kumar 	i2c_op.len = 1;
305a5c72737SRavi Kumar 	i2c_op.buf = redrv_data;
306a5c72737SRavi Kumar 	ret = axgbe_phy_i2c_xfer(pdata, &i2c_op);
307a5c72737SRavi Kumar 	if (ret) {
308a5c72737SRavi Kumar 		if ((ret == -EAGAIN) && retry--)
309a5c72737SRavi Kumar 			goto again2;
310a5c72737SRavi Kumar 
311a5c72737SRavi Kumar 		return ret;
312a5c72737SRavi Kumar 	}
313a5c72737SRavi Kumar 
314a5c72737SRavi Kumar 	if (redrv_data[0] != 0xff) {
315*e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(ERR, "Redriver write checksum error");
316a5c72737SRavi Kumar 		ret = -EIO;
317a5c72737SRavi Kumar 	}
318a5c72737SRavi Kumar 
319a5c72737SRavi Kumar 	return ret;
320a5c72737SRavi Kumar }
321a5c72737SRavi Kumar 
322a5c72737SRavi Kumar static int axgbe_phy_i2c_read(struct axgbe_port *pdata, unsigned int target,
323a5c72737SRavi Kumar 			      void *reg, unsigned int reg_len,
324a5c72737SRavi Kumar 			      void *val, unsigned int val_len)
325a5c72737SRavi Kumar {
326a5c72737SRavi Kumar 	struct axgbe_i2c_op i2c_op;
327a5c72737SRavi Kumar 	int retry, ret;
328a5c72737SRavi Kumar 
329a5c72737SRavi Kumar 	retry = 1;
330a5c72737SRavi Kumar again1:
331a5c72737SRavi Kumar 	/* Set the specified register to read */
332a5c72737SRavi Kumar 	i2c_op.cmd = AXGBE_I2C_CMD_WRITE;
333a5c72737SRavi Kumar 	i2c_op.target = target;
334a5c72737SRavi Kumar 	i2c_op.len = reg_len;
335a5c72737SRavi Kumar 	i2c_op.buf = reg;
336a5c72737SRavi Kumar 	ret = axgbe_phy_i2c_xfer(pdata, &i2c_op);
337a5c72737SRavi Kumar 	if (ret) {
338a5c72737SRavi Kumar 		if ((ret == -EAGAIN) && retry--)
339a5c72737SRavi Kumar 			goto again1;
340a5c72737SRavi Kumar 
341a5c72737SRavi Kumar 		return ret;
342a5c72737SRavi Kumar 	}
343a5c72737SRavi Kumar 
344a5c72737SRavi Kumar 	retry = 1;
345a5c72737SRavi Kumar again2:
3467be78d02SJosh Soref 	/* Read the specified register */
347a5c72737SRavi Kumar 	i2c_op.cmd = AXGBE_I2C_CMD_READ;
348a5c72737SRavi Kumar 	i2c_op.target = target;
349a5c72737SRavi Kumar 	i2c_op.len = val_len;
350a5c72737SRavi Kumar 	i2c_op.buf = val;
351a5c72737SRavi Kumar 	ret = axgbe_phy_i2c_xfer(pdata, &i2c_op);
352a5c72737SRavi Kumar 	if ((ret == -EAGAIN) && retry--)
353a5c72737SRavi Kumar 		goto again2;
354a5c72737SRavi Kumar 
355a5c72737SRavi Kumar 	return ret;
356a5c72737SRavi Kumar }
357a5c72737SRavi Kumar 
358a5c72737SRavi Kumar static int axgbe_phy_sfp_put_mux(struct axgbe_port *pdata)
359a5c72737SRavi Kumar {
360a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
361a5c72737SRavi Kumar 	struct axgbe_i2c_op i2c_op;
362a5c72737SRavi Kumar 	uint8_t mux_channel;
363a5c72737SRavi Kumar 
364a5c72737SRavi Kumar 	if (phy_data->sfp_comm == AXGBE_SFP_COMM_DIRECT)
365a5c72737SRavi Kumar 		return 0;
366a5c72737SRavi Kumar 
367a5c72737SRavi Kumar 	/* Select no mux channels */
368a5c72737SRavi Kumar 	mux_channel = 0;
369a5c72737SRavi Kumar 	i2c_op.cmd = AXGBE_I2C_CMD_WRITE;
370a5c72737SRavi Kumar 	i2c_op.target = phy_data->sfp_mux_address;
371a5c72737SRavi Kumar 	i2c_op.len = sizeof(mux_channel);
372a5c72737SRavi Kumar 	i2c_op.buf = &mux_channel;
373a5c72737SRavi Kumar 
374a5c72737SRavi Kumar 	return axgbe_phy_i2c_xfer(pdata, &i2c_op);
375a5c72737SRavi Kumar }
376a5c72737SRavi Kumar 
377a5c72737SRavi Kumar static int axgbe_phy_sfp_get_mux(struct axgbe_port *pdata)
378a5c72737SRavi Kumar {
379a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
380a5c72737SRavi Kumar 	struct axgbe_i2c_op i2c_op;
381a5c72737SRavi Kumar 	u8 mux_channel;
382a5c72737SRavi Kumar 
383a5c72737SRavi Kumar 	if (phy_data->sfp_comm == AXGBE_SFP_COMM_DIRECT)
384a5c72737SRavi Kumar 		return 0;
385a5c72737SRavi Kumar 
386a5c72737SRavi Kumar 	/* Select desired mux channel */
387a5c72737SRavi Kumar 	mux_channel = 1 << phy_data->sfp_mux_channel;
388a5c72737SRavi Kumar 	i2c_op.cmd = AXGBE_I2C_CMD_WRITE;
389a5c72737SRavi Kumar 	i2c_op.target = phy_data->sfp_mux_address;
390a5c72737SRavi Kumar 	i2c_op.len = sizeof(mux_channel);
391a5c72737SRavi Kumar 	i2c_op.buf = &mux_channel;
392a5c72737SRavi Kumar 
393a5c72737SRavi Kumar 	return axgbe_phy_i2c_xfer(pdata, &i2c_op);
394a5c72737SRavi Kumar }
395a5c72737SRavi Kumar 
396a5c72737SRavi Kumar static void axgbe_phy_put_comm_ownership(struct axgbe_port *pdata)
397a5c72737SRavi Kumar {
398a5c72737SRavi Kumar 	pthread_mutex_unlock(&pdata->phy_mutex);
399a5c72737SRavi Kumar }
400a5c72737SRavi Kumar 
401a5c72737SRavi Kumar static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata)
402a5c72737SRavi Kumar {
403a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
404a5c72737SRavi Kumar 	uint64_t timeout;
405a5c72737SRavi Kumar 	unsigned int mutex_id;
406a5c72737SRavi Kumar 
407a5c72737SRavi Kumar 	/* The I2C and MDIO/GPIO bus is multiplexed between multiple devices,
408a5c72737SRavi Kumar 	 * the driver needs to take the software mutex and then the hardware
409a5c72737SRavi Kumar 	 * mutexes before being able to use the busses.
410a5c72737SRavi Kumar 	 */
411a5c72737SRavi Kumar 	pthread_mutex_lock(&pdata->phy_mutex);
412a5c72737SRavi Kumar 
413a5c72737SRavi Kumar 	/* Clear the mutexes */
414a5c72737SRavi Kumar 	XP_IOWRITE(pdata, XP_I2C_MUTEX, AXGBE_MUTEX_RELEASE);
415a5c72737SRavi Kumar 	XP_IOWRITE(pdata, XP_MDIO_MUTEX, AXGBE_MUTEX_RELEASE);
416a5c72737SRavi Kumar 
417a5c72737SRavi Kumar 	/* Mutex formats are the same for I2C and MDIO/GPIO */
418a5c72737SRavi Kumar 	mutex_id = 0;
419a5c72737SRavi Kumar 	XP_SET_BITS(mutex_id, XP_I2C_MUTEX, ID, phy_data->port_id);
420a5c72737SRavi Kumar 	XP_SET_BITS(mutex_id, XP_I2C_MUTEX, ACTIVE, 1);
421a5c72737SRavi Kumar 
422a5c72737SRavi Kumar 	timeout = rte_get_timer_cycles() + (rte_get_timer_hz() * 5);
423a5c72737SRavi Kumar 	while (time_before(rte_get_timer_cycles(), timeout)) {
424a5c72737SRavi Kumar 		/* Must be all zeroes in order to obtain the mutex */
425a5c72737SRavi Kumar 		if (XP_IOREAD(pdata, XP_I2C_MUTEX) ||
426a5c72737SRavi Kumar 		    XP_IOREAD(pdata, XP_MDIO_MUTEX)) {
427a5c72737SRavi Kumar 			rte_delay_us(100);
428a5c72737SRavi Kumar 			continue;
429a5c72737SRavi Kumar 		}
430a5c72737SRavi Kumar 
431a5c72737SRavi Kumar 		/* Obtain the mutex */
432a5c72737SRavi Kumar 		XP_IOWRITE(pdata, XP_I2C_MUTEX, mutex_id);
433a5c72737SRavi Kumar 		XP_IOWRITE(pdata, XP_MDIO_MUTEX, mutex_id);
434a5c72737SRavi Kumar 
435a5c72737SRavi Kumar 		return 0;
436a5c72737SRavi Kumar 	}
437a5c72737SRavi Kumar 
438a5c72737SRavi Kumar 	pthread_mutex_unlock(&pdata->phy_mutex);
439a5c72737SRavi Kumar 
440*e99981afSDavid Marchand 	PMD_DRV_LOG_LINE(ERR, "unable to obtain hardware mutexes");
441a5c72737SRavi Kumar 
442a5c72737SRavi Kumar 	return -ETIMEDOUT;
443a5c72737SRavi Kumar }
444a5c72737SRavi Kumar 
445a5c72737SRavi Kumar static void axgbe_phy_sfp_phy_settings(struct axgbe_port *pdata)
446a5c72737SRavi Kumar {
447a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
448a5c72737SRavi Kumar 
449a5c72737SRavi Kumar 	if (phy_data->sfp_mod_absent) {
450a5c72737SRavi Kumar 		pdata->phy.speed = SPEED_UNKNOWN;
451a5c72737SRavi Kumar 		pdata->phy.duplex = DUPLEX_UNKNOWN;
452a5c72737SRavi Kumar 		pdata->phy.autoneg = AUTONEG_ENABLE;
453a5c72737SRavi Kumar 		pdata->phy.advertising = pdata->phy.supported;
454a5c72737SRavi Kumar 	}
455a5c72737SRavi Kumar 
456a5c72737SRavi Kumar 	pdata->phy.advertising &= ~ADVERTISED_Autoneg;
457a5c72737SRavi Kumar 	pdata->phy.advertising &= ~ADVERTISED_TP;
458a5c72737SRavi Kumar 	pdata->phy.advertising &= ~ADVERTISED_FIBRE;
459a5c72737SRavi Kumar 	pdata->phy.advertising &= ~ADVERTISED_100baseT_Full;
460a5c72737SRavi Kumar 	pdata->phy.advertising &= ~ADVERTISED_1000baseT_Full;
461a5c72737SRavi Kumar 	pdata->phy.advertising &= ~ADVERTISED_10000baseT_Full;
462a5c72737SRavi Kumar 	pdata->phy.advertising &= ~ADVERTISED_10000baseR_FEC;
463a5c72737SRavi Kumar 
464a5c72737SRavi Kumar 	switch (phy_data->sfp_base) {
465a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_T:
466a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_SX:
467a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_LX:
468a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_CX:
469a5c72737SRavi Kumar 		pdata->phy.speed = SPEED_UNKNOWN;
470a5c72737SRavi Kumar 		pdata->phy.duplex = DUPLEX_UNKNOWN;
471a5c72737SRavi Kumar 		pdata->phy.autoneg = AUTONEG_ENABLE;
472a5c72737SRavi Kumar 		pdata->phy.advertising |= ADVERTISED_Autoneg;
473a5c72737SRavi Kumar 		break;
474a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_SR:
475a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_LR:
476a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_LRM:
477a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_ER:
478a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_CR:
479a5c72737SRavi Kumar 	default:
480a5c72737SRavi Kumar 		pdata->phy.speed = SPEED_10000;
481a5c72737SRavi Kumar 		pdata->phy.duplex = DUPLEX_FULL;
482a5c72737SRavi Kumar 		pdata->phy.autoneg = AUTONEG_DISABLE;
483a5c72737SRavi Kumar 		break;
484a5c72737SRavi Kumar 	}
485a5c72737SRavi Kumar 
486a5c72737SRavi Kumar 	switch (phy_data->sfp_base) {
487a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_T:
488a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_CX:
489a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_CR:
490a5c72737SRavi Kumar 		pdata->phy.advertising |= ADVERTISED_TP;
491a5c72737SRavi Kumar 		break;
492a5c72737SRavi Kumar 	default:
493a5c72737SRavi Kumar 		pdata->phy.advertising |= ADVERTISED_FIBRE;
494a5c72737SRavi Kumar 	}
495a5c72737SRavi Kumar 
496a5c72737SRavi Kumar 	switch (phy_data->sfp_speed) {
497a5c72737SRavi Kumar 	case AXGBE_SFP_SPEED_100_1000:
4981f9d2d3aSVenkat Kumar Ande 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10)
4991f9d2d3aSVenkat Kumar Ande 			pdata->phy.advertising |= ADVERTISED_10baseT_Full;
500a5c72737SRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100)
501a5c72737SRavi Kumar 			pdata->phy.advertising |= ADVERTISED_100baseT_Full;
502a5c72737SRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000)
503a5c72737SRavi Kumar 			pdata->phy.advertising |= ADVERTISED_1000baseT_Full;
504a5c72737SRavi Kumar 		break;
505a5c72737SRavi Kumar 	case AXGBE_SFP_SPEED_1000:
506a5c72737SRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000)
507a5c72737SRavi Kumar 			pdata->phy.advertising |= ADVERTISED_1000baseT_Full;
508a5c72737SRavi Kumar 		break;
509a5c72737SRavi Kumar 	case AXGBE_SFP_SPEED_10000:
510a5c72737SRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000)
511a5c72737SRavi Kumar 			pdata->phy.advertising |= ADVERTISED_10000baseT_Full;
512a5c72737SRavi Kumar 		break;
513a5c72737SRavi Kumar 	default:
514a5c72737SRavi Kumar 		/* Choose the fastest supported speed */
515a5c72737SRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000)
516a5c72737SRavi Kumar 			pdata->phy.advertising |= ADVERTISED_10000baseT_Full;
517a5c72737SRavi Kumar 		else if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000)
518a5c72737SRavi Kumar 			pdata->phy.advertising |= ADVERTISED_1000baseT_Full;
519a5c72737SRavi Kumar 		else if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100)
520a5c72737SRavi Kumar 			pdata->phy.advertising |= ADVERTISED_100baseT_Full;
5211f9d2d3aSVenkat Kumar Ande 		else if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10)
5221f9d2d3aSVenkat Kumar Ande 			pdata->phy.advertising |= ADVERTISED_10baseT_Full;
523a5c72737SRavi Kumar 	}
524a5c72737SRavi Kumar }
525a5c72737SRavi Kumar 
526a5c72737SRavi Kumar static bool axgbe_phy_sfp_bit_rate(struct axgbe_sfp_eeprom *sfp_eeprom,
527a5c72737SRavi Kumar 				   enum axgbe_sfp_speed sfp_speed)
528a5c72737SRavi Kumar {
529b5587a39SVenkat Kumar Ande 	u8 *sfp_base, min;
530a5c72737SRavi Kumar 
531a5c72737SRavi Kumar 	sfp_base = sfp_eeprom->base;
532a5c72737SRavi Kumar 
533a5c72737SRavi Kumar 	switch (sfp_speed) {
534a5c72737SRavi Kumar 	case AXGBE_SFP_SPEED_1000:
535a5c72737SRavi Kumar 		min = AXGBE_SFP_BASE_BR_1GBE_MIN;
536a5c72737SRavi Kumar 		break;
537a5c72737SRavi Kumar 	case AXGBE_SFP_SPEED_10000:
538a5c72737SRavi Kumar 		min = AXGBE_SFP_BASE_BR_10GBE_MIN;
539a5c72737SRavi Kumar 		break;
540a5c72737SRavi Kumar 	default:
541a5c72737SRavi Kumar 		return false;
542a5c72737SRavi Kumar 	}
543a5c72737SRavi Kumar 
544b5587a39SVenkat Kumar Ande 	return sfp_base[AXGBE_SFP_BASE_BR] >= min;
545a5c72737SRavi Kumar }
546a5c72737SRavi Kumar 
547a5c72737SRavi Kumar static void axgbe_phy_sfp_external_phy(struct axgbe_port *pdata)
548a5c72737SRavi Kumar {
549a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
550a5c72737SRavi Kumar 
551a5c72737SRavi Kumar 	if (!phy_data->sfp_changed)
552a5c72737SRavi Kumar 		return;
553a5c72737SRavi Kumar 
554a5c72737SRavi Kumar 	phy_data->sfp_phy_avail = 0;
555a5c72737SRavi Kumar 
556a5c72737SRavi Kumar 	if (phy_data->sfp_base != AXGBE_SFP_BASE_1000_T)
557a5c72737SRavi Kumar 		return;
558a5c72737SRavi Kumar }
559a5c72737SRavi Kumar 
560a5c72737SRavi Kumar static bool axgbe_phy_belfuse_parse_quirks(struct axgbe_port *pdata)
561a5c72737SRavi Kumar {
562a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
563a5c72737SRavi Kumar 	struct axgbe_sfp_eeprom *sfp_eeprom = &phy_data->sfp_eeprom;
564a5c72737SRavi Kumar 
565a5c72737SRavi Kumar 	if (memcmp(&sfp_eeprom->base[AXGBE_SFP_BASE_VENDOR_NAME],
56627578231SAndy Green 		   AXGBE_BEL_FUSE_VENDOR, strlen(AXGBE_BEL_FUSE_VENDOR)))
567a5c72737SRavi Kumar 		return false;
568a770d00aSVenkat Kumar Ande 	/* For Bel-Fuse, use the extra AN flag */
569a770d00aSVenkat Kumar Ande 	pdata->an_again = 1;
570a5c72737SRavi Kumar 
5713abfda0fSVenkat Kumar Ande 	/* Reset PHY - wait for self-clearing reset bit to clear */
5723abfda0fSVenkat Kumar Ande 	pdata->phy_if.phy_impl.reset(pdata);
5733abfda0fSVenkat Kumar Ande 
574a5c72737SRavi Kumar 	if (!memcmp(&sfp_eeprom->base[AXGBE_SFP_BASE_VENDOR_PN],
57527578231SAndy Green 		    AXGBE_BEL_FUSE_PARTNO, strlen(AXGBE_BEL_FUSE_PARTNO))) {
576a5c72737SRavi Kumar 		phy_data->sfp_base = AXGBE_SFP_BASE_1000_SX;
577a5c72737SRavi Kumar 		phy_data->sfp_cable = AXGBE_SFP_CABLE_ACTIVE;
578a5c72737SRavi Kumar 		phy_data->sfp_speed = AXGBE_SFP_SPEED_1000;
579a5c72737SRavi Kumar 		return true;
580a5c72737SRavi Kumar 	}
581a5c72737SRavi Kumar 
582a5c72737SRavi Kumar 	return false;
583a5c72737SRavi Kumar }
584a5c72737SRavi Kumar 
585a5c72737SRavi Kumar static bool axgbe_phy_sfp_parse_quirks(struct axgbe_port *pdata)
586a5c72737SRavi Kumar {
587a5c72737SRavi Kumar 	if (axgbe_phy_belfuse_parse_quirks(pdata))
588a5c72737SRavi Kumar 		return true;
589a5c72737SRavi Kumar 
590a5c72737SRavi Kumar 	return false;
591a5c72737SRavi Kumar }
592a5c72737SRavi Kumar 
593a5c72737SRavi Kumar static void axgbe_phy_sfp_parse_eeprom(struct axgbe_port *pdata)
594a5c72737SRavi Kumar {
595a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
596a5c72737SRavi Kumar 	struct axgbe_sfp_eeprom *sfp_eeprom = &phy_data->sfp_eeprom;
597a5c72737SRavi Kumar 	uint8_t *sfp_base;
598a5c72737SRavi Kumar 
599a5c72737SRavi Kumar 	sfp_base = sfp_eeprom->base;
600a5c72737SRavi Kumar 
601a5c72737SRavi Kumar 	if (sfp_base[AXGBE_SFP_BASE_ID] != AXGBE_SFP_ID_SFP)
602a5c72737SRavi Kumar 		return;
603a5c72737SRavi Kumar 
604a5c72737SRavi Kumar 	if (sfp_base[AXGBE_SFP_BASE_EXT_ID] != AXGBE_SFP_EXT_ID_SFP)
605a5c72737SRavi Kumar 		return;
606a5c72737SRavi Kumar 
607936e294cSGirish Nandibasappa 	axgbe_phy_sfp_parse_quirks(pdata);
608a5c72737SRavi Kumar 
6094823ccdbSVenkat Kumar Ande 	/* Assume FIBER cable unless told otherwise */
610a5c72737SRavi Kumar 	if (sfp_base[AXGBE_SFP_BASE_CABLE] & AXGBE_SFP_BASE_CABLE_PASSIVE) {
611a5c72737SRavi Kumar 		phy_data->sfp_cable = AXGBE_SFP_CABLE_PASSIVE;
612a5c72737SRavi Kumar 		phy_data->sfp_cable_len = sfp_base[AXGBE_SFP_BASE_CU_CABLE_LEN];
6134823ccdbSVenkat Kumar Ande 	} else if (sfp_base[AXGBE_SFP_BASE_CABLE] & AXGBE_SFP_BASE_CABLE_ACTIVE) {
614a5c72737SRavi Kumar 		phy_data->sfp_cable = AXGBE_SFP_CABLE_ACTIVE;
6154823ccdbSVenkat Kumar Ande 	} else {
6164823ccdbSVenkat Kumar Ande 		phy_data->sfp_cable = AXGBE_SFP_CABLE_FIBER;
617a5c72737SRavi Kumar 	}
618a5c72737SRavi Kumar 
619a5c72737SRavi Kumar 	/* Determine the type of SFP */
6204823ccdbSVenkat Kumar Ande 	if (phy_data->sfp_cable != AXGBE_SFP_CABLE_FIBER &&
6214eefb1b1SVenkat Kumar Ande 		 axgbe_phy_sfp_bit_rate(sfp_eeprom, AXGBE_SFP_SPEED_10000))
6224eefb1b1SVenkat Kumar Ande 		phy_data->sfp_base = AXGBE_SFP_BASE_10000_CR;
6234eefb1b1SVenkat Kumar Ande 	else if (sfp_base[AXGBE_SFP_BASE_10GBE_CC] & AXGBE_SFP_BASE_10GBE_CC_SR)
624a5c72737SRavi Kumar 		phy_data->sfp_base = AXGBE_SFP_BASE_10000_SR;
625a5c72737SRavi Kumar 	else if (sfp_base[AXGBE_SFP_BASE_10GBE_CC] & AXGBE_SFP_BASE_10GBE_CC_LR)
626a5c72737SRavi Kumar 		phy_data->sfp_base = AXGBE_SFP_BASE_10000_LR;
627a5c72737SRavi Kumar 	else if (sfp_base[AXGBE_SFP_BASE_10GBE_CC] &
628a5c72737SRavi Kumar 		 AXGBE_SFP_BASE_10GBE_CC_LRM)
629a5c72737SRavi Kumar 		phy_data->sfp_base = AXGBE_SFP_BASE_10000_LRM;
630a5c72737SRavi Kumar 	else if (sfp_base[AXGBE_SFP_BASE_10GBE_CC] & AXGBE_SFP_BASE_10GBE_CC_ER)
631a5c72737SRavi Kumar 		phy_data->sfp_base = AXGBE_SFP_BASE_10000_ER;
632a5c72737SRavi Kumar 	else if (sfp_base[AXGBE_SFP_BASE_1GBE_CC] & AXGBE_SFP_BASE_1GBE_CC_SX)
633a5c72737SRavi Kumar 		phy_data->sfp_base = AXGBE_SFP_BASE_1000_SX;
634a5c72737SRavi Kumar 	else if (sfp_base[AXGBE_SFP_BASE_1GBE_CC] & AXGBE_SFP_BASE_1GBE_CC_LX)
635a5c72737SRavi Kumar 		phy_data->sfp_base = AXGBE_SFP_BASE_1000_LX;
636a5c72737SRavi Kumar 	else if (sfp_base[AXGBE_SFP_BASE_1GBE_CC] & AXGBE_SFP_BASE_1GBE_CC_CX)
637a5c72737SRavi Kumar 		phy_data->sfp_base = AXGBE_SFP_BASE_1000_CX;
638a5c72737SRavi Kumar 	else if (sfp_base[AXGBE_SFP_BASE_1GBE_CC] & AXGBE_SFP_BASE_1GBE_CC_T)
639a5c72737SRavi Kumar 		phy_data->sfp_base = AXGBE_SFP_BASE_1000_T;
640a5c72737SRavi Kumar 
641a5c72737SRavi Kumar 	switch (phy_data->sfp_base) {
642a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_T:
643a5c72737SRavi Kumar 		phy_data->sfp_speed = AXGBE_SFP_SPEED_100_1000;
644a5c72737SRavi Kumar 		break;
645a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_SX:
646a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_LX:
647a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_CX:
648a5c72737SRavi Kumar 		phy_data->sfp_speed = AXGBE_SFP_SPEED_1000;
649a5c72737SRavi Kumar 		break;
650a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_SR:
651a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_LR:
652a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_LRM:
653a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_ER:
654a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_10000_CR:
655a5c72737SRavi Kumar 		phy_data->sfp_speed = AXGBE_SFP_SPEED_10000;
656a5c72737SRavi Kumar 		break;
657a5c72737SRavi Kumar 	default:
658a5c72737SRavi Kumar 		break;
659a5c72737SRavi Kumar 	}
660a5c72737SRavi Kumar }
661a5c72737SRavi Kumar 
662a5c72737SRavi Kumar static bool axgbe_phy_sfp_verify_eeprom(uint8_t cc_in, uint8_t *buf,
663a5c72737SRavi Kumar 					unsigned int len)
664a5c72737SRavi Kumar {
665a5c72737SRavi Kumar 	uint8_t cc;
666a5c72737SRavi Kumar 
667a5c72737SRavi Kumar 	for (cc = 0; len; buf++, len--)
668a5c72737SRavi Kumar 		cc += *buf;
669a5c72737SRavi Kumar 
670aca000c0SVenkat Kumar Ande 	return cc == cc_in;
671a5c72737SRavi Kumar }
672a5c72737SRavi Kumar 
673a5c72737SRavi Kumar static int axgbe_phy_sfp_read_eeprom(struct axgbe_port *pdata)
674a5c72737SRavi Kumar {
675a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
676a5c72737SRavi Kumar 	struct axgbe_sfp_eeprom sfp_eeprom;
677a5c72737SRavi Kumar 	uint8_t eeprom_addr;
678a5c72737SRavi Kumar 	int ret;
679a5c72737SRavi Kumar 
680a5c72737SRavi Kumar 	ret = axgbe_phy_sfp_get_mux(pdata);
681a5c72737SRavi Kumar 	if (ret) {
682*e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(ERR, "I2C error setting SFP MUX");
683a5c72737SRavi Kumar 		return ret;
684a5c72737SRavi Kumar 	}
685a5c72737SRavi Kumar 
686a5c72737SRavi Kumar 	/* Read the SFP serial ID eeprom */
687a5c72737SRavi Kumar 	eeprom_addr = 0;
688a5c72737SRavi Kumar 	ret = axgbe_phy_i2c_read(pdata, AXGBE_SFP_SERIAL_ID_ADDRESS,
689a5c72737SRavi Kumar 				 &eeprom_addr, sizeof(eeprom_addr),
690a5c72737SRavi Kumar 				 &sfp_eeprom, sizeof(sfp_eeprom));
691a5c72737SRavi Kumar 	if (ret) {
692*e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(ERR, "I2C error reading SFP EEPROM");
693a5c72737SRavi Kumar 		goto put;
694a5c72737SRavi Kumar 	}
695a5c72737SRavi Kumar 
696a5c72737SRavi Kumar 	/* Validate the contents read */
697a5c72737SRavi Kumar 	if (!axgbe_phy_sfp_verify_eeprom(sfp_eeprom.base[AXGBE_SFP_BASE_CC],
698a5c72737SRavi Kumar 					 sfp_eeprom.base,
699a5c72737SRavi Kumar 					 sizeof(sfp_eeprom.base) - 1)) {
700a5c72737SRavi Kumar 		ret = -EINVAL;
701a5c72737SRavi Kumar 		goto put;
702a5c72737SRavi Kumar 	}
703a5c72737SRavi Kumar 
704a5c72737SRavi Kumar 	if (!axgbe_phy_sfp_verify_eeprom(sfp_eeprom.extd[AXGBE_SFP_EXTD_CC],
705a5c72737SRavi Kumar 					 sfp_eeprom.extd,
706a5c72737SRavi Kumar 					 sizeof(sfp_eeprom.extd) - 1)) {
707a5c72737SRavi Kumar 		ret = -EINVAL;
708a5c72737SRavi Kumar 		goto put;
709a5c72737SRavi Kumar 	}
710a5c72737SRavi Kumar 
711a5c72737SRavi Kumar 	/* Check for an added or changed SFP */
712a5c72737SRavi Kumar 	if (memcmp(&phy_data->sfp_eeprom, &sfp_eeprom, sizeof(sfp_eeprom))) {
713a5c72737SRavi Kumar 		phy_data->sfp_changed = 1;
714a5c72737SRavi Kumar 		memcpy(&phy_data->sfp_eeprom, &sfp_eeprom, sizeof(sfp_eeprom));
715a5c72737SRavi Kumar 	} else {
716a5c72737SRavi Kumar 		phy_data->sfp_changed = 0;
717a5c72737SRavi Kumar 	}
718a5c72737SRavi Kumar 
719a5c72737SRavi Kumar put:
720a5c72737SRavi Kumar 	axgbe_phy_sfp_put_mux(pdata);
721a5c72737SRavi Kumar 
722a5c72737SRavi Kumar 	return ret;
723a5c72737SRavi Kumar }
724a5c72737SRavi Kumar 
725a5c72737SRavi Kumar static void axgbe_phy_sfp_signals(struct axgbe_port *pdata)
726a5c72737SRavi Kumar {
727a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
728a5c72737SRavi Kumar 	unsigned int gpio_input;
729a5c72737SRavi Kumar 	u8 gpio_reg, gpio_ports[2];
730a5c72737SRavi Kumar 	int ret;
731a5c72737SRavi Kumar 
732a5c72737SRavi Kumar 	/* Read the input port registers */
733a5c72737SRavi Kumar 	gpio_reg = 0;
734a5c72737SRavi Kumar 	ret = axgbe_phy_i2c_read(pdata, phy_data->sfp_gpio_address,
735a5c72737SRavi Kumar 				 &gpio_reg, sizeof(gpio_reg),
736a5c72737SRavi Kumar 				 gpio_ports, sizeof(gpio_ports));
737a5c72737SRavi Kumar 	if (ret) {
738*e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(ERR, "I2C error reading SFP GPIOs");
739a5c72737SRavi Kumar 		return;
740a5c72737SRavi Kumar 	}
741a5c72737SRavi Kumar 
742a5c72737SRavi Kumar 	gpio_input = (gpio_ports[1] << 8) | gpio_ports[0];
743a5c72737SRavi Kumar 
744a5c72737SRavi Kumar 	if (phy_data->sfp_gpio_mask & AXGBE_GPIO_NO_MOD_ABSENT) {
745a5c72737SRavi Kumar 		/* No GPIO, just assume the module is present for now */
746a5c72737SRavi Kumar 		phy_data->sfp_mod_absent = 0;
747a5c72737SRavi Kumar 	} else {
748a5c72737SRavi Kumar 		if (!(gpio_input & (1 << phy_data->sfp_gpio_mod_absent)))
749a5c72737SRavi Kumar 			phy_data->sfp_mod_absent = 0;
750a5c72737SRavi Kumar 	}
751a5c72737SRavi Kumar 
752a5c72737SRavi Kumar 	if (!(phy_data->sfp_gpio_mask & AXGBE_GPIO_NO_RX_LOS) &&
753a5c72737SRavi Kumar 	    (gpio_input & (1 << phy_data->sfp_gpio_rx_los)))
754a5c72737SRavi Kumar 		phy_data->sfp_rx_los = 1;
755a5c72737SRavi Kumar 
756a5c72737SRavi Kumar 	if (!(phy_data->sfp_gpio_mask & AXGBE_GPIO_NO_TX_FAULT) &&
757a5c72737SRavi Kumar 	    (gpio_input & (1 << phy_data->sfp_gpio_tx_fault)))
758a5c72737SRavi Kumar 		phy_data->sfp_tx_fault = 1;
759a5c72737SRavi Kumar }
760a5c72737SRavi Kumar 
761a5c72737SRavi Kumar static void axgbe_phy_sfp_mod_absent(struct axgbe_port *pdata)
762a5c72737SRavi Kumar {
763a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
764a5c72737SRavi Kumar 
765a5c72737SRavi Kumar 	phy_data->sfp_mod_absent = 1;
766a5c72737SRavi Kumar 	phy_data->sfp_phy_avail = 0;
767a5c72737SRavi Kumar 	memset(&phy_data->sfp_eeprom, 0, sizeof(phy_data->sfp_eeprom));
768a5c72737SRavi Kumar }
769a5c72737SRavi Kumar 
770a5c72737SRavi Kumar static void axgbe_phy_sfp_reset(struct axgbe_phy_data *phy_data)
771a5c72737SRavi Kumar {
772a5c72737SRavi Kumar 	phy_data->sfp_rx_los = 0;
773a5c72737SRavi Kumar 	phy_data->sfp_tx_fault = 0;
774a5c72737SRavi Kumar 	phy_data->sfp_mod_absent = 1;
775a5c72737SRavi Kumar 	phy_data->sfp_base = AXGBE_SFP_BASE_UNKNOWN;
776a5c72737SRavi Kumar 	phy_data->sfp_cable = AXGBE_SFP_CABLE_UNKNOWN;
777a5c72737SRavi Kumar 	phy_data->sfp_speed = AXGBE_SFP_SPEED_UNKNOWN;
778a5c72737SRavi Kumar }
779a5c72737SRavi Kumar 
7804216cdc0SChandu Babu N static const char *axgbe_base_as_string(enum axgbe_sfp_base sfp_base)
7814216cdc0SChandu Babu N {
7824216cdc0SChandu Babu N 	switch (sfp_base) {
7834216cdc0SChandu Babu N 	case AXGBE_SFP_BASE_1000_T:
7844216cdc0SChandu Babu N 		return "1G_T";
7854216cdc0SChandu Babu N 	case AXGBE_SFP_BASE_1000_SX:
7864216cdc0SChandu Babu N 		return "1G_SX";
7874216cdc0SChandu Babu N 	case AXGBE_SFP_BASE_1000_LX:
7884216cdc0SChandu Babu N 		return "1G_LX";
7894216cdc0SChandu Babu N 	case AXGBE_SFP_BASE_1000_CX:
7904216cdc0SChandu Babu N 		return "1G_CX";
7914216cdc0SChandu Babu N 	case AXGBE_SFP_BASE_10000_SR:
7924216cdc0SChandu Babu N 		return "10G_SR";
7934216cdc0SChandu Babu N 	case AXGBE_SFP_BASE_10000_LR:
7944216cdc0SChandu Babu N 		return "10G_LR";
7954216cdc0SChandu Babu N 	case AXGBE_SFP_BASE_10000_LRM:
7964216cdc0SChandu Babu N 		return "10G_LRM";
7974216cdc0SChandu Babu N 	case AXGBE_SFP_BASE_10000_ER:
7984216cdc0SChandu Babu N 		return "10G_ER";
7994216cdc0SChandu Babu N 	case AXGBE_SFP_BASE_10000_CR:
8004216cdc0SChandu Babu N 		return "10G_CR";
8014216cdc0SChandu Babu N 	default:
8024216cdc0SChandu Babu N 		return "Unknown";
8034216cdc0SChandu Babu N 	}
8044216cdc0SChandu Babu N }
8054216cdc0SChandu Babu N 
806a5c72737SRavi Kumar static void axgbe_phy_sfp_detect(struct axgbe_port *pdata)
807a5c72737SRavi Kumar {
808a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
809a5c72737SRavi Kumar 	int ret;
810a5c72737SRavi Kumar 
811a770d00aSVenkat Kumar Ande 	/* Clear the extra AN flag */
812a770d00aSVenkat Kumar Ande 	pdata->an_again = 0;
813a770d00aSVenkat Kumar Ande 
814a5c72737SRavi Kumar 	/* Reset the SFP signals and info */
815a5c72737SRavi Kumar 	axgbe_phy_sfp_reset(phy_data);
816a5c72737SRavi Kumar 
817a5c72737SRavi Kumar 	ret = axgbe_phy_get_comm_ownership(pdata);
818a5c72737SRavi Kumar 	if (ret)
819a5c72737SRavi Kumar 		return;
820a5c72737SRavi Kumar 
821a5c72737SRavi Kumar 	/* Read the SFP signals and check for module presence */
822a5c72737SRavi Kumar 	axgbe_phy_sfp_signals(pdata);
823a5c72737SRavi Kumar 	if (phy_data->sfp_mod_absent) {
824a5c72737SRavi Kumar 		axgbe_phy_sfp_mod_absent(pdata);
825a5c72737SRavi Kumar 		goto put;
826a5c72737SRavi Kumar 	}
827a5c72737SRavi Kumar 
828a5c72737SRavi Kumar 	ret = axgbe_phy_sfp_read_eeprom(pdata);
829a5c72737SRavi Kumar 	if (ret) {
830a5c72737SRavi Kumar 		/* Treat any error as if there isn't an SFP plugged in */
831a5c72737SRavi Kumar 		axgbe_phy_sfp_reset(phy_data);
832a5c72737SRavi Kumar 		axgbe_phy_sfp_mod_absent(pdata);
833a5c72737SRavi Kumar 		goto put;
834a5c72737SRavi Kumar 	}
835a5c72737SRavi Kumar 
836a5c72737SRavi Kumar 	axgbe_phy_sfp_parse_eeprom(pdata);
837a5c72737SRavi Kumar 	axgbe_phy_sfp_external_phy(pdata);
838a5c72737SRavi Kumar 
839*e99981afSDavid Marchand 	PMD_DRV_LOG_LINE(DEBUG, "SFP Base: %s",
8404216cdc0SChandu Babu N 		    axgbe_base_as_string(phy_data->sfp_base));
8414216cdc0SChandu Babu N 
842a5c72737SRavi Kumar put:
843a5c72737SRavi Kumar 	axgbe_phy_sfp_phy_settings(pdata);
844a5c72737SRavi Kumar 	axgbe_phy_put_comm_ownership(pdata);
845a5c72737SRavi Kumar }
846a5c72737SRavi Kumar 
847a5c72737SRavi Kumar static void axgbe_phy_phydev_flowctrl(struct axgbe_port *pdata)
848a5c72737SRavi Kumar {
849a5c72737SRavi Kumar 	pdata->phy.tx_pause = 0;
850a5c72737SRavi Kumar 	pdata->phy.rx_pause = 0;
851a5c72737SRavi Kumar }
852a5c72737SRavi Kumar 
853a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_an73_redrv_outcome(struct axgbe_port *pdata)
854a5c72737SRavi Kumar {
855a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
856a5c72737SRavi Kumar 	enum axgbe_mode mode;
857a5c72737SRavi Kumar 	unsigned int ad_reg, lp_reg;
858a5c72737SRavi Kumar 
859a5c72737SRavi Kumar 	pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
860a5c72737SRavi Kumar 	pdata->phy.lp_advertising |= ADVERTISED_Backplane;
861a5c72737SRavi Kumar 
862a5c72737SRavi Kumar 	/* Use external PHY to determine flow control */
863a5c72737SRavi Kumar 	if (pdata->phy.pause_autoneg)
864a5c72737SRavi Kumar 		axgbe_phy_phydev_flowctrl(pdata);
865a5c72737SRavi Kumar 
866a5c72737SRavi Kumar 	/* Compare Advertisement and Link Partner register 2 */
867a5c72737SRavi Kumar 	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
868a5c72737SRavi Kumar 	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
869a5c72737SRavi Kumar 	if (lp_reg & 0x80)
870a5c72737SRavi Kumar 		pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full;
871a5c72737SRavi Kumar 	if (lp_reg & 0x20)
872a5c72737SRavi Kumar 		pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full;
873a5c72737SRavi Kumar 
874a5c72737SRavi Kumar 	ad_reg &= lp_reg;
875a5c72737SRavi Kumar 	if (ad_reg & 0x80) {
876a5c72737SRavi Kumar 		switch (phy_data->port_mode) {
877a5c72737SRavi Kumar 		case AXGBE_PORT_MODE_BACKPLANE:
878443ab5aaSSelwin Sebastian 		case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG:
879a5c72737SRavi Kumar 			mode = AXGBE_MODE_KR;
880a5c72737SRavi Kumar 			break;
881a5c72737SRavi Kumar 		default:
882a5c72737SRavi Kumar 			mode = AXGBE_MODE_SFI;
883a5c72737SRavi Kumar 			break;
884a5c72737SRavi Kumar 		}
885a5c72737SRavi Kumar 	} else if (ad_reg & 0x20) {
886a5c72737SRavi Kumar 		switch (phy_data->port_mode) {
887a5c72737SRavi Kumar 		case AXGBE_PORT_MODE_BACKPLANE:
888443ab5aaSSelwin Sebastian 		case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG:
889a5c72737SRavi Kumar 			mode = AXGBE_MODE_KX_1000;
890a5c72737SRavi Kumar 			break;
891a5c72737SRavi Kumar 		case AXGBE_PORT_MODE_1000BASE_X:
892a5c72737SRavi Kumar 			mode = AXGBE_MODE_X;
893a5c72737SRavi Kumar 			break;
894a5c72737SRavi Kumar 		case AXGBE_PORT_MODE_SFP:
895a5c72737SRavi Kumar 			switch (phy_data->sfp_base) {
896a5c72737SRavi Kumar 			case AXGBE_SFP_BASE_1000_T:
897a5c72737SRavi Kumar 				mode = AXGBE_MODE_SGMII_1000;
898a5c72737SRavi Kumar 				break;
899a5c72737SRavi Kumar 			case AXGBE_SFP_BASE_1000_SX:
900a5c72737SRavi Kumar 			case AXGBE_SFP_BASE_1000_LX:
901a5c72737SRavi Kumar 			case AXGBE_SFP_BASE_1000_CX:
902a5c72737SRavi Kumar 			default:
903a5c72737SRavi Kumar 				mode = AXGBE_MODE_X;
904a5c72737SRavi Kumar 				break;
905a5c72737SRavi Kumar 			}
906a5c72737SRavi Kumar 			break;
907a5c72737SRavi Kumar 		default:
908a5c72737SRavi Kumar 			mode = AXGBE_MODE_SGMII_1000;
909a5c72737SRavi Kumar 			break;
910a5c72737SRavi Kumar 		}
911a5c72737SRavi Kumar 	} else {
912a5c72737SRavi Kumar 		mode = AXGBE_MODE_UNKNOWN;
913a5c72737SRavi Kumar 	}
914a5c72737SRavi Kumar 
915a5c72737SRavi Kumar 	/* Compare Advertisement and Link Partner register 3 */
916a5c72737SRavi Kumar 	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
917a5c72737SRavi Kumar 	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
918a5c72737SRavi Kumar 	if (lp_reg & 0xc000)
919a5c72737SRavi Kumar 		pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC;
920a5c72737SRavi Kumar 
921a5c72737SRavi Kumar 	return mode;
922a5c72737SRavi Kumar }
923a5c72737SRavi Kumar 
924a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_an73_outcome(struct axgbe_port *pdata)
925a5c72737SRavi Kumar {
926a5c72737SRavi Kumar 	enum axgbe_mode mode;
927a5c72737SRavi Kumar 	unsigned int ad_reg, lp_reg;
928a5c72737SRavi Kumar 
929a5c72737SRavi Kumar 	pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
930a5c72737SRavi Kumar 	pdata->phy.lp_advertising |= ADVERTISED_Backplane;
931a5c72737SRavi Kumar 
932a5c72737SRavi Kumar 	/* Compare Advertisement and Link Partner register 1 */
933a5c72737SRavi Kumar 	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
934a5c72737SRavi Kumar 	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
935a5c72737SRavi Kumar 	if (lp_reg & 0x400)
936a5c72737SRavi Kumar 		pdata->phy.lp_advertising |= ADVERTISED_Pause;
937a5c72737SRavi Kumar 	if (lp_reg & 0x800)
938a5c72737SRavi Kumar 		pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause;
939a5c72737SRavi Kumar 
940a5c72737SRavi Kumar 	if (pdata->phy.pause_autoneg) {
941a5c72737SRavi Kumar 		/* Set flow control based on auto-negotiation result */
942a5c72737SRavi Kumar 		pdata->phy.tx_pause = 0;
943a5c72737SRavi Kumar 		pdata->phy.rx_pause = 0;
944a5c72737SRavi Kumar 
945a5c72737SRavi Kumar 		if (ad_reg & lp_reg & 0x400) {
946a5c72737SRavi Kumar 			pdata->phy.tx_pause = 1;
947a5c72737SRavi Kumar 			pdata->phy.rx_pause = 1;
948a5c72737SRavi Kumar 		} else if (ad_reg & lp_reg & 0x800) {
949a5c72737SRavi Kumar 			if (ad_reg & 0x400)
950a5c72737SRavi Kumar 				pdata->phy.rx_pause = 1;
951a5c72737SRavi Kumar 			else if (lp_reg & 0x400)
952a5c72737SRavi Kumar 				pdata->phy.tx_pause = 1;
953a5c72737SRavi Kumar 		}
954a5c72737SRavi Kumar 	}
955a5c72737SRavi Kumar 
956a5c72737SRavi Kumar 	/* Compare Advertisement and Link Partner register 2 */
957a5c72737SRavi Kumar 	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
958a5c72737SRavi Kumar 	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
959a5c72737SRavi Kumar 	if (lp_reg & 0x80)
960a5c72737SRavi Kumar 		pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full;
961a5c72737SRavi Kumar 	if (lp_reg & 0x20)
962a5c72737SRavi Kumar 		pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full;
963a5c72737SRavi Kumar 
964a5c72737SRavi Kumar 	ad_reg &= lp_reg;
965a5c72737SRavi Kumar 	if (ad_reg & 0x80)
966a5c72737SRavi Kumar 		mode = AXGBE_MODE_KR;
967a5c72737SRavi Kumar 	else if (ad_reg & 0x20)
968a5c72737SRavi Kumar 		mode = AXGBE_MODE_KX_1000;
969a5c72737SRavi Kumar 	else
970a5c72737SRavi Kumar 		mode = AXGBE_MODE_UNKNOWN;
971a5c72737SRavi Kumar 
972a5c72737SRavi Kumar 	/* Compare Advertisement and Link Partner register 3 */
973a5c72737SRavi Kumar 	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
974a5c72737SRavi Kumar 	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
975a5c72737SRavi Kumar 	if (lp_reg & 0xc000)
976a5c72737SRavi Kumar 		pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC;
977a5c72737SRavi Kumar 
978a5c72737SRavi Kumar 	return mode;
979a5c72737SRavi Kumar }
980a5c72737SRavi Kumar 
981102b6ec3SGirish Nandibasappa static enum axgbe_mode axgbe_phy_an37_sgmii_outcome(struct axgbe_port *pdata)
982102b6ec3SGirish Nandibasappa {
983102b6ec3SGirish Nandibasappa 	enum axgbe_mode mode;
984102b6ec3SGirish Nandibasappa 
985102b6ec3SGirish Nandibasappa 	pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
986102b6ec3SGirish Nandibasappa 	pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Full;
987102b6ec3SGirish Nandibasappa 
988102b6ec3SGirish Nandibasappa 	if (pdata->phy.pause_autoneg)
989102b6ec3SGirish Nandibasappa 		axgbe_phy_phydev_flowctrl(pdata);
990102b6ec3SGirish Nandibasappa 
991102b6ec3SGirish Nandibasappa 	switch (pdata->an_status & AXGBE_SGMII_AN_LINK_SPEED) {
9921f9d2d3aSVenkat Kumar Ande 	case AXGBE_SGMII_AN_LINK_SPEED_10:
9931f9d2d3aSVenkat Kumar Ande 		if (pdata->an_status & AXGBE_SGMII_AN_LINK_DUPLEX) {
9941f9d2d3aSVenkat Kumar Ande 			pdata->phy.lp_advertising |= ADVERTISED_10baseT_Full;
9951f9d2d3aSVenkat Kumar Ande 			mode = AXGBE_MODE_SGMII_10;
9961f9d2d3aSVenkat Kumar Ande 		} else {
9971f9d2d3aSVenkat Kumar Ande 			mode = AXGBE_MODE_UNKNOWN;
9981f9d2d3aSVenkat Kumar Ande 		}
9991f9d2d3aSVenkat Kumar Ande 		break;
1000102b6ec3SGirish Nandibasappa 	case AXGBE_SGMII_AN_LINK_SPEED_100:
1001102b6ec3SGirish Nandibasappa 		if (pdata->an_status & AXGBE_SGMII_AN_LINK_DUPLEX) {
1002102b6ec3SGirish Nandibasappa 			pdata->phy.lp_advertising |= ADVERTISED_100baseT_Full;
1003102b6ec3SGirish Nandibasappa 			mode = AXGBE_MODE_SGMII_100;
1004102b6ec3SGirish Nandibasappa 		} else {
1005102b6ec3SGirish Nandibasappa 			mode = AXGBE_MODE_UNKNOWN;
1006102b6ec3SGirish Nandibasappa 		}
1007102b6ec3SGirish Nandibasappa 		break;
1008102b6ec3SGirish Nandibasappa 	case AXGBE_SGMII_AN_LINK_SPEED_1000:
1009102b6ec3SGirish Nandibasappa 		if (pdata->an_status & AXGBE_SGMII_AN_LINK_DUPLEX) {
1010102b6ec3SGirish Nandibasappa 			pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Full;
1011102b6ec3SGirish Nandibasappa 			mode = AXGBE_MODE_SGMII_1000;
1012102b6ec3SGirish Nandibasappa 		} else {
1013102b6ec3SGirish Nandibasappa 			/* Half-duplex not supported */
1014102b6ec3SGirish Nandibasappa 			mode = AXGBE_MODE_UNKNOWN;
1015102b6ec3SGirish Nandibasappa 		}
1016102b6ec3SGirish Nandibasappa 		break;
1017102b6ec3SGirish Nandibasappa 	default:
1018102b6ec3SGirish Nandibasappa 		mode = AXGBE_MODE_UNKNOWN;
1019102b6ec3SGirish Nandibasappa 		break;
1020102b6ec3SGirish Nandibasappa 	}
1021102b6ec3SGirish Nandibasappa 	return mode;
1022102b6ec3SGirish Nandibasappa }
1023102b6ec3SGirish Nandibasappa 
1024a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_an_outcome(struct axgbe_port *pdata)
1025a5c72737SRavi Kumar {
1026a5c72737SRavi Kumar 	switch (pdata->an_mode) {
1027a5c72737SRavi Kumar 	case AXGBE_AN_MODE_CL73:
1028a5c72737SRavi Kumar 		return axgbe_phy_an73_outcome(pdata);
1029a5c72737SRavi Kumar 	case AXGBE_AN_MODE_CL73_REDRV:
1030a5c72737SRavi Kumar 		return axgbe_phy_an73_redrv_outcome(pdata);
1031a5c72737SRavi Kumar 	case AXGBE_AN_MODE_CL37:
1032a5c72737SRavi Kumar 	case AXGBE_AN_MODE_CL37_SGMII:
1033102b6ec3SGirish Nandibasappa 		return axgbe_phy_an37_sgmii_outcome(pdata);
1034a5c72737SRavi Kumar 	default:
1035a5c72737SRavi Kumar 		return AXGBE_MODE_UNKNOWN;
1036a5c72737SRavi Kumar 	}
1037a5c72737SRavi Kumar }
1038a5c72737SRavi Kumar 
1039a5c72737SRavi Kumar static unsigned int axgbe_phy_an_advertising(struct axgbe_port *pdata)
1040a5c72737SRavi Kumar {
1041a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1042a5c72737SRavi Kumar 	unsigned int advertising;
1043a5c72737SRavi Kumar 
1044a5c72737SRavi Kumar 	/* Without a re-driver, just return current advertising */
1045a5c72737SRavi Kumar 	if (!phy_data->redrv)
1046a5c72737SRavi Kumar 		return pdata->phy.advertising;
1047a5c72737SRavi Kumar 
1048a5c72737SRavi Kumar 	/* With the KR re-driver we need to advertise a single speed */
1049a5c72737SRavi Kumar 	advertising = pdata->phy.advertising;
1050a5c72737SRavi Kumar 	advertising &= ~ADVERTISED_1000baseKX_Full;
1051a5c72737SRavi Kumar 	advertising &= ~ADVERTISED_10000baseKR_Full;
1052a5c72737SRavi Kumar 
1053a5c72737SRavi Kumar 	switch (phy_data->port_mode) {
1054a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE:
1055443ab5aaSSelwin Sebastian 	case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG:
1056a5c72737SRavi Kumar 		advertising |= ADVERTISED_10000baseKR_Full;
1057a5c72737SRavi Kumar 		break;
1058a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE_2500:
1059a5c72737SRavi Kumar 		advertising |= ADVERTISED_1000baseKX_Full;
1060a5c72737SRavi Kumar 		break;
1061a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_T:
1062a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_X:
1063a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_NBASE_T:
1064a5c72737SRavi Kumar 		advertising |= ADVERTISED_1000baseKX_Full;
1065a5c72737SRavi Kumar 		break;
1066a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_T:
1067*e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(ERR, "10GBASE_T mode is not supported");
1068a5c72737SRavi Kumar 		break;
1069a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_R:
1070a5c72737SRavi Kumar 		advertising |= ADVERTISED_10000baseKR_Full;
1071a5c72737SRavi Kumar 		break;
1072a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_SFP:
1073a5c72737SRavi Kumar 		switch (phy_data->sfp_base) {
1074a5c72737SRavi Kumar 		case AXGBE_SFP_BASE_1000_T:
1075a5c72737SRavi Kumar 		case AXGBE_SFP_BASE_1000_SX:
1076a5c72737SRavi Kumar 		case AXGBE_SFP_BASE_1000_LX:
1077a5c72737SRavi Kumar 		case AXGBE_SFP_BASE_1000_CX:
1078a5c72737SRavi Kumar 			advertising |= ADVERTISED_1000baseKX_Full;
1079a5c72737SRavi Kumar 			break;
1080a5c72737SRavi Kumar 		default:
1081a5c72737SRavi Kumar 			advertising |= ADVERTISED_10000baseKR_Full;
1082a5c72737SRavi Kumar 			break;
1083a5c72737SRavi Kumar 		}
1084a5c72737SRavi Kumar 		break;
1085a5c72737SRavi Kumar 	default:
1086a5c72737SRavi Kumar 		advertising |= ADVERTISED_10000baseKR_Full;
1087a5c72737SRavi Kumar 		break;
1088a5c72737SRavi Kumar 	}
1089a5c72737SRavi Kumar 
1090a5c72737SRavi Kumar 	return advertising;
1091a5c72737SRavi Kumar }
1092a5c72737SRavi Kumar 
1093a5c72737SRavi Kumar static int axgbe_phy_an_config(struct axgbe_port *pdata __rte_unused)
1094a5c72737SRavi Kumar {
1095a5c72737SRavi Kumar 	return 0;
1096a5c72737SRavi Kumar 	/* Dummy API since there is no case to support
10977be78d02SJosh Soref 	 * external phy devices registered through kernel APIs
1098a5c72737SRavi Kumar 	 */
1099a5c72737SRavi Kumar }
1100a5c72737SRavi Kumar 
1101a5c72737SRavi Kumar static enum axgbe_an_mode axgbe_phy_an_sfp_mode(struct axgbe_phy_data *phy_data)
1102a5c72737SRavi Kumar {
1103a5c72737SRavi Kumar 	switch (phy_data->sfp_base) {
1104a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_T:
1105a5c72737SRavi Kumar 		return AXGBE_AN_MODE_CL37_SGMII;
1106a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_SX:
1107a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_LX:
1108a5c72737SRavi Kumar 	case AXGBE_SFP_BASE_1000_CX:
1109a5c72737SRavi Kumar 		return AXGBE_AN_MODE_CL37;
1110a5c72737SRavi Kumar 	default:
1111a5c72737SRavi Kumar 		return AXGBE_AN_MODE_NONE;
1112a5c72737SRavi Kumar 	}
1113a5c72737SRavi Kumar }
1114a5c72737SRavi Kumar 
1115a5c72737SRavi Kumar static enum axgbe_an_mode axgbe_phy_an_mode(struct axgbe_port *pdata)
1116a5c72737SRavi Kumar {
1117a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1118a5c72737SRavi Kumar 
1119a5c72737SRavi Kumar 	/* A KR re-driver will always require CL73 AN */
1120a5c72737SRavi Kumar 	if (phy_data->redrv)
1121a5c72737SRavi Kumar 		return AXGBE_AN_MODE_CL73_REDRV;
1122a5c72737SRavi Kumar 
1123a5c72737SRavi Kumar 	switch (phy_data->port_mode) {
1124a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE:
1125a5c72737SRavi Kumar 		return AXGBE_AN_MODE_CL73;
1126443ab5aaSSelwin Sebastian 	case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG:
1127a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE_2500:
1128a5c72737SRavi Kumar 		return AXGBE_AN_MODE_NONE;
1129a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_T:
1130a5c72737SRavi Kumar 		return AXGBE_AN_MODE_CL37_SGMII;
1131a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_X:
1132a5c72737SRavi Kumar 		return AXGBE_AN_MODE_CL37;
1133a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_NBASE_T:
1134a5c72737SRavi Kumar 		return AXGBE_AN_MODE_CL37_SGMII;
1135a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_T:
1136a5c72737SRavi Kumar 		return AXGBE_AN_MODE_CL73;
1137a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_R:
1138a5c72737SRavi Kumar 		return AXGBE_AN_MODE_NONE;
1139a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_SFP:
1140a5c72737SRavi Kumar 		return axgbe_phy_an_sfp_mode(phy_data);
1141a5c72737SRavi Kumar 	default:
1142a5c72737SRavi Kumar 		return AXGBE_AN_MODE_NONE;
1143a5c72737SRavi Kumar 	}
1144a5c72737SRavi Kumar }
1145a5c72737SRavi Kumar 
1146a5c72737SRavi Kumar static int axgbe_phy_set_redrv_mode_mdio(struct axgbe_port *pdata,
1147a5c72737SRavi Kumar 					 enum axgbe_phy_redrv_mode mode)
1148a5c72737SRavi Kumar {
1149a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1150a5c72737SRavi Kumar 	u16 redrv_reg, redrv_val;
1151a5c72737SRavi Kumar 
1152a5c72737SRavi Kumar 	redrv_reg = AXGBE_PHY_REDRV_MODE_REG + (phy_data->redrv_lane * 0x1000);
1153a5c72737SRavi Kumar 	redrv_val = (u16)mode;
1154a5c72737SRavi Kumar 
1155627ab524SVenkat Kumar Ande 	return pdata->hw_if.write_ext_mii_regs_c22(pdata,
1156627ab524SVenkat Kumar Ande 		phy_data->redrv_addr, redrv_reg, redrv_val);
1157a5c72737SRavi Kumar }
1158a5c72737SRavi Kumar 
1159a5c72737SRavi Kumar static int axgbe_phy_set_redrv_mode_i2c(struct axgbe_port *pdata,
1160a5c72737SRavi Kumar 					enum axgbe_phy_redrv_mode mode)
1161a5c72737SRavi Kumar {
1162a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1163a5c72737SRavi Kumar 	unsigned int redrv_reg;
1164a5c72737SRavi Kumar 	int ret;
1165a5c72737SRavi Kumar 
1166a5c72737SRavi Kumar 	/* Calculate the register to write */
1167a5c72737SRavi Kumar 	redrv_reg = AXGBE_PHY_REDRV_MODE_REG + (phy_data->redrv_lane * 0x1000);
1168a5c72737SRavi Kumar 
1169a5c72737SRavi Kumar 	ret = axgbe_phy_redrv_write(pdata, redrv_reg, mode);
1170a5c72737SRavi Kumar 
1171a5c72737SRavi Kumar 	return ret;
1172a5c72737SRavi Kumar }
1173a5c72737SRavi Kumar 
1174a5c72737SRavi Kumar static void axgbe_phy_set_redrv_mode(struct axgbe_port *pdata)
1175a5c72737SRavi Kumar {
1176a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1177a5c72737SRavi Kumar 	enum axgbe_phy_redrv_mode mode;
1178a5c72737SRavi Kumar 	int ret;
1179a5c72737SRavi Kumar 
1180a5c72737SRavi Kumar 	if (!phy_data->redrv)
1181a5c72737SRavi Kumar 		return;
1182a5c72737SRavi Kumar 
1183a5c72737SRavi Kumar 	mode = AXGBE_PHY_REDRV_MODE_CX;
1184a5c72737SRavi Kumar 	if ((phy_data->port_mode == AXGBE_PORT_MODE_SFP) &&
1185a5c72737SRavi Kumar 	    (phy_data->sfp_base != AXGBE_SFP_BASE_1000_CX) &&
1186a5c72737SRavi Kumar 	    (phy_data->sfp_base != AXGBE_SFP_BASE_10000_CR))
1187a5c72737SRavi Kumar 		mode = AXGBE_PHY_REDRV_MODE_SR;
1188a5c72737SRavi Kumar 
1189a5c72737SRavi Kumar 	ret = axgbe_phy_get_comm_ownership(pdata);
1190a5c72737SRavi Kumar 	if (ret)
1191a5c72737SRavi Kumar 		return;
1192a5c72737SRavi Kumar 
1193a5c72737SRavi Kumar 	if (phy_data->redrv_if)
1194a5c72737SRavi Kumar 		axgbe_phy_set_redrv_mode_i2c(pdata, mode);
1195a5c72737SRavi Kumar 	else
1196a5c72737SRavi Kumar 		axgbe_phy_set_redrv_mode_mdio(pdata, mode);
1197a5c72737SRavi Kumar 
1198a5c72737SRavi Kumar 	axgbe_phy_put_comm_ownership(pdata);
1199a5c72737SRavi Kumar }
1200a5c72737SRavi Kumar 
12016c04898fSVenkat Kumar Ande #define MAX_RX_ADAPT_RETRIES		1
12026c04898fSVenkat Kumar Ande #define XGBE_PMA_RX_VAL_SIG_MASK	(XGBE_PMA_RX_SIG_DET_0_MASK | \
12036c04898fSVenkat Kumar Ande 					 XGBE_PMA_RX_VALID_0_MASK)
12046c04898fSVenkat Kumar Ande 
12056c04898fSVenkat Kumar Ande static void axgbe_set_rx_adap_mode(struct axgbe_port *pdata,
12066c04898fSVenkat Kumar Ande 				  enum axgbe_mode mode)
12076c04898fSVenkat Kumar Ande {
12086c04898fSVenkat Kumar Ande 	if (pdata->rx_adapt_retries++ >= MAX_RX_ADAPT_RETRIES) {
12096c04898fSVenkat Kumar Ande 		pdata->rx_adapt_retries = 0;
12106c04898fSVenkat Kumar Ande 		return;
12116c04898fSVenkat Kumar Ande 	}
12126c04898fSVenkat Kumar Ande 
12136c04898fSVenkat Kumar Ande 	axgbe_phy_perform_ratechange(pdata,
12146c04898fSVenkat Kumar Ande 				    mode == AXGBE_MODE_KR ?
12156c04898fSVenkat Kumar Ande 				    AXGBE_MB_CMD_SET_10G_KR :
12166c04898fSVenkat Kumar Ande 				    AXGBE_MB_CMD_SET_10G_SFI,
12176c04898fSVenkat Kumar Ande 				    AXGBE_MB_SUBCMD_RX_ADAP);
12186c04898fSVenkat Kumar Ande }
12196c04898fSVenkat Kumar Ande 
12206c04898fSVenkat Kumar Ande static void axgbe_rx_adaptation(struct axgbe_port *pdata)
12216c04898fSVenkat Kumar Ande {
12226c04898fSVenkat Kumar Ande 	struct axgbe_phy_data *phy_data = pdata->phy_data;
12236c04898fSVenkat Kumar Ande 	unsigned int reg;
12246c04898fSVenkat Kumar Ande 
12256c04898fSVenkat Kumar Ande 	/* step 2: force PCS to send RX_ADAPT Req to PHY */
12266c04898fSVenkat Kumar Ande 	XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_EQ_CTRL4,
12276c04898fSVenkat Kumar Ande 			 XGBE_PMA_RX_AD_REQ_MASK, XGBE_PMA_RX_AD_REQ_ENABLE);
12286c04898fSVenkat Kumar Ande 
12296c04898fSVenkat Kumar Ande 	/* Step 3: Wait for RX_ADAPT ACK from the PHY */
12306c04898fSVenkat Kumar Ande 	rte_delay_ms(200);
12316c04898fSVenkat Kumar Ande 
12326c04898fSVenkat Kumar Ande 	/* Software polls for coefficient update command (given by local PHY) */
12336c04898fSVenkat Kumar Ande 	reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_PHY_RX_EQ_CEU);
12346c04898fSVenkat Kumar Ande 
12356c04898fSVenkat Kumar Ande 	/* Clear the RX_AD_REQ bit */
12366c04898fSVenkat Kumar Ande 	XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_EQ_CTRL4,
12376c04898fSVenkat Kumar Ande 			 XGBE_PMA_RX_AD_REQ_MASK, XGBE_PMA_RX_AD_REQ_DISABLE);
12386c04898fSVenkat Kumar Ande 
12396c04898fSVenkat Kumar Ande 	/* Check if coefficient update command is set */
12406c04898fSVenkat Kumar Ande 	if ((reg & XGBE_PMA_CFF_UPDT_MASK) != XGBE_PMA_CFF_UPDT_MASK)
12416c04898fSVenkat Kumar Ande 		goto set_mode;
12426c04898fSVenkat Kumar Ande 
12436c04898fSVenkat Kumar Ande 	/* Step 4: Check for Block lock */
12446c04898fSVenkat Kumar Ande 
12456c04898fSVenkat Kumar Ande 	/* Link status is latched low, so read once to clear
12466c04898fSVenkat Kumar Ande 	 * and then read again to get current state
12476c04898fSVenkat Kumar Ande 	 */
12486c04898fSVenkat Kumar Ande 	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
12496c04898fSVenkat Kumar Ande 	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
12506c04898fSVenkat Kumar Ande 	if (reg & MDIO_STAT1_LSTATUS) {
12516c04898fSVenkat Kumar Ande 		/* If the block lock is found, update the helpers
12526c04898fSVenkat Kumar Ande 		 * and declare the link up
12536c04898fSVenkat Kumar Ande 		 */
1254*e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(NOTICE, "Rx adaptation - Block_lock done");
12556c04898fSVenkat Kumar Ande 		pdata->rx_adapt_done = true;
12566c04898fSVenkat Kumar Ande 		pdata->mode_set = false;
12576c04898fSVenkat Kumar Ande 		return;
12586c04898fSVenkat Kumar Ande 	}
12596c04898fSVenkat Kumar Ande 
12606c04898fSVenkat Kumar Ande set_mode:
12616c04898fSVenkat Kumar Ande 	axgbe_set_rx_adap_mode(pdata, phy_data->cur_mode);
12626c04898fSVenkat Kumar Ande }
12636c04898fSVenkat Kumar Ande 
12646c04898fSVenkat Kumar Ande static void axgbe_phy_rx_adaptation(struct axgbe_port *pdata)
12656c04898fSVenkat Kumar Ande {
12666c04898fSVenkat Kumar Ande 	unsigned int reg;
12676c04898fSVenkat Kumar Ande 
12686c04898fSVenkat Kumar Ande rx_adapt_reinit:
12696c04898fSVenkat Kumar Ande 	reg = XMDIO_READ_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_LSTS,
12706c04898fSVenkat Kumar Ande 			      XGBE_PMA_RX_VAL_SIG_MASK);
12716c04898fSVenkat Kumar Ande 
12726c04898fSVenkat Kumar Ande 	/* step 1: Check for RX_VALID && LF_SIGDET */
12736c04898fSVenkat Kumar Ande 	if ((reg & XGBE_PMA_RX_VAL_SIG_MASK) != XGBE_PMA_RX_VAL_SIG_MASK) {
1274*e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(NOTICE, "RX_VALID or LF_SIGDET is unset, issue rrc");
12756c04898fSVenkat Kumar Ande 		axgbe_phy_rrc(pdata);
12766c04898fSVenkat Kumar Ande 		if (pdata->rx_adapt_retries++ >= MAX_RX_ADAPT_RETRIES) {
12776c04898fSVenkat Kumar Ande 			pdata->rx_adapt_retries = 0;
12786c04898fSVenkat Kumar Ande 			return;
12796c04898fSVenkat Kumar Ande 		}
12806c04898fSVenkat Kumar Ande 		goto rx_adapt_reinit;
12816c04898fSVenkat Kumar Ande 	}
12826c04898fSVenkat Kumar Ande 
12836c04898fSVenkat Kumar Ande 	/* perform rx adaptation */
12846c04898fSVenkat Kumar Ande 	axgbe_rx_adaptation(pdata);
12856c04898fSVenkat Kumar Ande }
12866c04898fSVenkat Kumar Ande 
1287cd48955bSSelwin Sebastian static void axgbe_phy_rx_reset(struct axgbe_port *pdata)
1288cd48955bSSelwin Sebastian {
1289cd48955bSSelwin Sebastian 	int reg;
1290cd48955bSSelwin Sebastian 
1291cd48955bSSelwin Sebastian 	reg = XMDIO_READ_BITS(pdata, MDIO_MMD_PCS, MDIO_PCS_DIGITAL_STAT,
1292cd48955bSSelwin Sebastian 			      XGBE_PCS_PSEQ_STATE_MASK);
1293cd48955bSSelwin Sebastian 	if (reg == XGBE_PCS_PSEQ_STATE_POWER_GOOD) {
1294cd48955bSSelwin Sebastian 		/* Mailbox command timed out, reset of RX block is required.
1295cd48955bSSelwin Sebastian 		 * This can be done by asseting the reset bit and wait for
1296cd48955bSSelwin Sebastian 		 * its compeletion.
1297cd48955bSSelwin Sebastian 		 */
1298cd48955bSSelwin Sebastian 		XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1,
1299cd48955bSSelwin Sebastian 				 XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_ON);
1300cd48955bSSelwin Sebastian 		rte_delay_us(20);
1301cd48955bSSelwin Sebastian 		XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1,
1302cd48955bSSelwin Sebastian 				 XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_OFF);
1303cd48955bSSelwin Sebastian 		rte_delay_us(45);
1304*e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(ERR, "firmware mailbox reset performed");
1305cd48955bSSelwin Sebastian 	}
1306cd48955bSSelwin Sebastian }
1307cd48955bSSelwin Sebastian 
1308cd48955bSSelwin Sebastian 
130909b0a36cSSelwin Sebastian static void axgbe_phy_pll_ctrl(struct axgbe_port *pdata, bool enable)
131009b0a36cSSelwin Sebastian {
13111c68b393SVenkat Kumar Ande 	/* PLL_CTRL feature needs to be enabled for fixed PHY modes (Non-Autoneg) only */
13121c68b393SVenkat Kumar Ande 	if (pdata->phy.autoneg != AUTONEG_DISABLE)
13131c68b393SVenkat Kumar Ande 		return;
13141c68b393SVenkat Kumar Ande 
131509b0a36cSSelwin Sebastian 	XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_MISC_CTRL0,
131609b0a36cSSelwin Sebastian 			XGBE_PMA_PLL_CTRL_MASK,
131709b0a36cSSelwin Sebastian 			enable ? XGBE_PMA_PLL_CTRL_SET
131809b0a36cSSelwin Sebastian 			: XGBE_PMA_PLL_CTRL_CLEAR);
131909b0a36cSSelwin Sebastian 
132009b0a36cSSelwin Sebastian 	/* Wait for command to complete */
132109b0a36cSSelwin Sebastian 	rte_delay_us(150);
132209b0a36cSSelwin Sebastian }
132309b0a36cSSelwin Sebastian 
13240df8d8dfSSelwin Sebastian static void axgbe_phy_perform_ratechange(struct axgbe_port *pdata,
1325cf96031aSVenkat Kumar Ande 		enum axgbe_mb_cmd cmd, enum axgbe_mb_subcmd sub_cmd)
1326a5c72737SRavi Kumar {
13270df8d8dfSSelwin Sebastian 	unsigned int s0 = 0;
13280df8d8dfSSelwin Sebastian 	unsigned int wait;
132909b0a36cSSelwin Sebastian 	/* Clear the PLL so that it helps in power down sequence */
133009b0a36cSSelwin Sebastian 	axgbe_phy_pll_ctrl(pdata, false);
133109b0a36cSSelwin Sebastian 
13324216cdc0SChandu Babu N 	/* Log if a previous command did not complete */
1333cd48955bSSelwin Sebastian 	if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) {
1334*e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(NOTICE, "firmware mailbox not ready for command");
1335cd48955bSSelwin Sebastian 		axgbe_phy_rx_reset(pdata);
1336cd48955bSSelwin Sebastian 	}
1337a5c72737SRavi Kumar 
13380df8d8dfSSelwin Sebastian 	/* Construct the command */
13390df8d8dfSSelwin Sebastian 	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, cmd);
13400df8d8dfSSelwin Sebastian 	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, sub_cmd);
13410df8d8dfSSelwin Sebastian 
13420df8d8dfSSelwin Sebastian 	/* Issue the command */
13430df8d8dfSSelwin Sebastian 	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0);
13440df8d8dfSSelwin Sebastian 	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
13450df8d8dfSSelwin Sebastian 	XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
1346a5c72737SRavi Kumar 
1347a5c72737SRavi Kumar 	/* Wait for command to complete */
1348a5c72737SRavi Kumar 	wait = AXGBE_RATECHANGE_COUNT;
1349a5c72737SRavi Kumar 	while (wait--) {
1350a5c72737SRavi Kumar 		if (!XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS))
13516c04898fSVenkat Kumar Ande 			goto do_rx_adaptation;
1352a5c72737SRavi Kumar 		rte_delay_us(1500);
1353a5c72737SRavi Kumar 	}
1354*e99981afSDavid Marchand 	PMD_DRV_LOG_LINE(NOTICE, "firmware mailbox command did not complete");
1355cd48955bSSelwin Sebastian 	/* Reset on error */
1356cd48955bSSelwin Sebastian 	axgbe_phy_rx_reset(pdata);
13576c04898fSVenkat Kumar Ande 	goto reenable_pll;
13586c04898fSVenkat Kumar Ande 
13596c04898fSVenkat Kumar Ande 
13606c04898fSVenkat Kumar Ande do_rx_adaptation:
13616c04898fSVenkat Kumar Ande 	if (pdata->en_rx_adap && sub_cmd == AXGBE_MB_SUBCMD_RX_ADAP &&
13626c04898fSVenkat Kumar Ande 	    (cmd == AXGBE_MB_CMD_SET_10G_KR || cmd == AXGBE_MB_CMD_SET_10G_SFI)) {
1363*e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(NOTICE, "Enabling RX adaptation");
13646c04898fSVenkat Kumar Ande 		pdata->mode_set = true;
13656c04898fSVenkat Kumar Ande 		axgbe_phy_rx_adaptation(pdata);
13666c04898fSVenkat Kumar Ande 		/* return from here to avoid enabling PLL ctrl
13676c04898fSVenkat Kumar Ande 		 * during adaptation phase
13686c04898fSVenkat Kumar Ande 		 */
13696c04898fSVenkat Kumar Ande 		return;
13706c04898fSVenkat Kumar Ande 	}
13716c04898fSVenkat Kumar Ande 
137209b0a36cSSelwin Sebastian 
137309b0a36cSSelwin Sebastian reenable_pll:
13741c68b393SVenkat Kumar Ande 	/* Enable PLL re-initialization, not needed for PHY Power Off and RRC cmds */
1375cf96031aSVenkat Kumar Ande 	if (cmd != AXGBE_MB_CMD_POWER_OFF &&
1376cf96031aSVenkat Kumar Ande 		cmd != AXGBE_MB_CMD_RRC)
137709b0a36cSSelwin Sebastian 		axgbe_phy_pll_ctrl(pdata, true);
1378a5c72737SRavi Kumar }
1379a5c72737SRavi Kumar 
1380a5c72737SRavi Kumar static void axgbe_phy_rrc(struct axgbe_port *pdata)
1381a5c72737SRavi Kumar {
1382a5c72737SRavi Kumar 
1383a5c72737SRavi Kumar 
1384a5c72737SRavi Kumar 	/* Receiver Reset Cycle */
1385cf96031aSVenkat Kumar Ande 	axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_RRC, AXGBE_MB_SUBCMD_NONE);
13864216cdc0SChandu Babu N 
1387*e99981afSDavid Marchand 	PMD_DRV_LOG_LINE(DEBUG, "receiver reset complete");
1388a5c72737SRavi Kumar }
1389a5c72737SRavi Kumar 
1390a5c72737SRavi Kumar static void axgbe_phy_power_off(struct axgbe_port *pdata)
1391a5c72737SRavi Kumar {
1392a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1393a5c72737SRavi Kumar 
13940df8d8dfSSelwin Sebastian 	/* Power off */
1395cf96031aSVenkat Kumar Ande 	axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_POWER_OFF, AXGBE_MB_SUBCMD_NONE);
1396a5c72737SRavi Kumar 
1397a5c72737SRavi Kumar 	phy_data->cur_mode = AXGBE_MODE_UNKNOWN;
13984216cdc0SChandu Babu N 
1399*e99981afSDavid Marchand 	PMD_DRV_LOG_LINE(DEBUG, "phy powered off");
1400a5c72737SRavi Kumar }
1401a5c72737SRavi Kumar 
14026c04898fSVenkat Kumar Ande static bool enable_rx_adap(struct axgbe_port *pdata, enum axgbe_mode mode)
14036c04898fSVenkat Kumar Ande {
14046c04898fSVenkat Kumar Ande 	struct axgbe_phy_data *phy_data = pdata->phy_data;
14056c04898fSVenkat Kumar Ande 	unsigned int ver;
14066c04898fSVenkat Kumar Ande 
14076c04898fSVenkat Kumar Ande 	/* Rx-Adaptation is not supported on older platforms(< 0x30H) */
14086c04898fSVenkat Kumar Ande 	ver = AXGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER);
14096c04898fSVenkat Kumar Ande 	if (ver < 0x30)
14106c04898fSVenkat Kumar Ande 		return false;
14116c04898fSVenkat Kumar Ande 
14126c04898fSVenkat Kumar Ande 	/* Re-driver models 4223 && 4227 do not support Rx-Adaptation */
14136c04898fSVenkat Kumar Ande 	if (phy_data->redrv &&
14146c04898fSVenkat Kumar Ande 	    (phy_data->redrv_model == AXGBE_PHY_REDRV_MODEL_4223 ||
14156c04898fSVenkat Kumar Ande 	     phy_data->redrv_model == AXGBE_PHY_REDRV_MODEL_4227))
14166c04898fSVenkat Kumar Ande 		return false;
14176c04898fSVenkat Kumar Ande 
14186c04898fSVenkat Kumar Ande 	/* 10G KR mode with AN does not support Rx-Adaptation */
14196c04898fSVenkat Kumar Ande 	if (mode == AXGBE_MODE_KR &&
14206c04898fSVenkat Kumar Ande 	    phy_data->port_mode != AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG)
14216c04898fSVenkat Kumar Ande 		return false;
14226c04898fSVenkat Kumar Ande 
14236c04898fSVenkat Kumar Ande 	pdata->en_rx_adap = 1;
14246c04898fSVenkat Kumar Ande 	return true;
14256c04898fSVenkat Kumar Ande }
14266c04898fSVenkat Kumar Ande 
1427a5c72737SRavi Kumar static void axgbe_phy_sfi_mode(struct axgbe_port *pdata)
1428a5c72737SRavi Kumar {
1429a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1430a5c72737SRavi Kumar 
1431a5c72737SRavi Kumar 	axgbe_phy_set_redrv_mode(pdata);
1432a5c72737SRavi Kumar 
1433a5c72737SRavi Kumar 	/* 10G/SFI */
1434a5c72737SRavi Kumar 	if (phy_data->sfp_cable != AXGBE_SFP_CABLE_PASSIVE) {
14356c04898fSVenkat Kumar Ande 		pdata->en_rx_adap = 0;
1436cf96031aSVenkat Kumar Ande 		axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_SET_10G_SFI,
1437cf96031aSVenkat Kumar Ande 							AXGBE_MB_SUBCMD_ACTIVE);
14386c04898fSVenkat Kumar Ande 	} else if ((phy_data->sfp_cable == AXGBE_SFP_CABLE_PASSIVE) &&
14396c04898fSVenkat Kumar Ande 				(enable_rx_adap(pdata, AXGBE_MODE_SFI))) {
14406c04898fSVenkat Kumar Ande 		axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_SET_10G_SFI,
14416c04898fSVenkat Kumar Ande 						AXGBE_MB_SUBCMD_RX_ADAP);
1442a5c72737SRavi Kumar 	} else {
1443a5c72737SRavi Kumar 		if (phy_data->sfp_cable_len <= 1)
1444cf96031aSVenkat Kumar Ande 			axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_SET_10G_SFI,
1445cf96031aSVenkat Kumar Ande 							AXGBE_MB_SUBCMD_PASSIVE_1M);
1446a5c72737SRavi Kumar 		else if (phy_data->sfp_cable_len <= 3)
1447cf96031aSVenkat Kumar Ande 			axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_SET_10G_SFI,
1448cf96031aSVenkat Kumar Ande 							AXGBE_MB_SUBCMD_PASSIVE_3M);
1449a5c72737SRavi Kumar 		else
1450cf96031aSVenkat Kumar Ande 			axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_SET_10G_SFI,
1451cf96031aSVenkat Kumar Ande 							AXGBE_MB_SUBCMD_PASSIVE_OTHER);
1452a5c72737SRavi Kumar 	}
1453a5c72737SRavi Kumar 
1454a5c72737SRavi Kumar 	phy_data->cur_mode = AXGBE_MODE_SFI;
14554216cdc0SChandu Babu N 
1456*e99981afSDavid Marchand 	PMD_DRV_LOG_LINE(DEBUG, "10GbE SFI mode set");
1457a5c72737SRavi Kumar }
1458a5c72737SRavi Kumar 
1459a5c72737SRavi Kumar static void axgbe_phy_kr_mode(struct axgbe_port *pdata)
1460a5c72737SRavi Kumar {
1461a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1462a5c72737SRavi Kumar 
1463a5c72737SRavi Kumar 	axgbe_phy_set_redrv_mode(pdata);
1464a5c72737SRavi Kumar 
1465a5c72737SRavi Kumar 	/* 10G/KR */
14666c04898fSVenkat Kumar Ande 	if (enable_rx_adap(pdata, AXGBE_MODE_KR))
14676c04898fSVenkat Kumar Ande 		axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_SET_10G_KR,
14686c04898fSVenkat Kumar Ande 						AXGBE_MB_SUBCMD_RX_ADAP);
14696c04898fSVenkat Kumar Ande 	else
1470cf96031aSVenkat Kumar Ande 		axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_SET_10G_KR,
1471cf96031aSVenkat Kumar Ande 						AXGBE_MB_SUBCMD_NONE);
1472a5c72737SRavi Kumar 	phy_data->cur_mode = AXGBE_MODE_KR;
14734216cdc0SChandu Babu N 
1474*e99981afSDavid Marchand 	PMD_DRV_LOG_LINE(DEBUG, "10GbE KR mode set");
1475a5c72737SRavi Kumar }
1476a5c72737SRavi Kumar 
1477936e294cSGirish Nandibasappa static void axgbe_phy_kx_2500_mode(struct axgbe_port *pdata)
1478936e294cSGirish Nandibasappa {
1479936e294cSGirish Nandibasappa 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1480936e294cSGirish Nandibasappa 
1481936e294cSGirish Nandibasappa 	axgbe_phy_set_redrv_mode(pdata);
14820df8d8dfSSelwin Sebastian 
1483936e294cSGirish Nandibasappa 	/* 2.5G/KX */
1484cf96031aSVenkat Kumar Ande 	axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_SET_2_5G, AXGBE_MB_SUBCMD_NONE);
1485936e294cSGirish Nandibasappa 	phy_data->cur_mode = AXGBE_MODE_KX_2500;
1486936e294cSGirish Nandibasappa }
1487936e294cSGirish Nandibasappa 
1488936e294cSGirish Nandibasappa static void axgbe_phy_sgmii_1000_mode(struct axgbe_port *pdata)
1489936e294cSGirish Nandibasappa {
1490936e294cSGirish Nandibasappa 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1491936e294cSGirish Nandibasappa 
1492936e294cSGirish Nandibasappa 	axgbe_phy_set_redrv_mode(pdata);
1493936e294cSGirish Nandibasappa 
1494936e294cSGirish Nandibasappa 	/* 1G/SGMII */
1495cf96031aSVenkat Kumar Ande 	axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_SET_1G, AXGBE_MB_SUBCMD_1G_SGMII);
1496936e294cSGirish Nandibasappa 
1497936e294cSGirish Nandibasappa 	phy_data->cur_mode = AXGBE_MODE_SGMII_1000;
1498936e294cSGirish Nandibasappa }
1499936e294cSGirish Nandibasappa 
15001f9d2d3aSVenkat Kumar Ande static void axgbe_phy_sgmii_10_mode(struct axgbe_port *pdata)
15011f9d2d3aSVenkat Kumar Ande {
15021f9d2d3aSVenkat Kumar Ande 	struct axgbe_phy_data *phy_data = pdata->phy_data;
15031f9d2d3aSVenkat Kumar Ande 
15041f9d2d3aSVenkat Kumar Ande 	axgbe_phy_set_redrv_mode(pdata);
15051f9d2d3aSVenkat Kumar Ande 
15061f9d2d3aSVenkat Kumar Ande 	/* 10M/SGMII */
15071f9d2d3aSVenkat Kumar Ande 	axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_SET_1G, AXGBE_MB_SUBCMD_10MBITS);
15081f9d2d3aSVenkat Kumar Ande 
15091f9d2d3aSVenkat Kumar Ande 	phy_data->cur_mode = AXGBE_MODE_SGMII_10;
15101f9d2d3aSVenkat Kumar Ande }
15111f9d2d3aSVenkat Kumar Ande 
1512a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_cur_mode(struct axgbe_port *pdata)
1513a5c72737SRavi Kumar {
1514a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1515a5c72737SRavi Kumar 
1516a5c72737SRavi Kumar 	return phy_data->cur_mode;
1517a5c72737SRavi Kumar }
1518a5c72737SRavi Kumar 
1519a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_switch_baset_mode(struct axgbe_port *pdata)
1520a5c72737SRavi Kumar {
1521a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1522a5c72737SRavi Kumar 
1523a5c72737SRavi Kumar 	/* No switching if not 10GBase-T */
1524a5c72737SRavi Kumar 	if (phy_data->port_mode != AXGBE_PORT_MODE_10GBASE_T)
1525a5c72737SRavi Kumar 		return axgbe_phy_cur_mode(pdata);
1526a5c72737SRavi Kumar 
1527a5c72737SRavi Kumar 	switch (axgbe_phy_cur_mode(pdata)) {
15281f9d2d3aSVenkat Kumar Ande 	case AXGBE_MODE_SGMII_10:
1529a5c72737SRavi Kumar 	case AXGBE_MODE_SGMII_100:
1530a5c72737SRavi Kumar 	case AXGBE_MODE_SGMII_1000:
1531a5c72737SRavi Kumar 		return AXGBE_MODE_KR;
1532d7344a7bSVenkat Kumar Ande 	case AXGBE_MODE_KX_2500:
1533d7344a7bSVenkat Kumar Ande 		return AXGBE_MODE_SGMII_1000;
1534a5c72737SRavi Kumar 	case AXGBE_MODE_KR:
1535a5c72737SRavi Kumar 	default:
1536d7344a7bSVenkat Kumar Ande 		return AXGBE_MODE_KX_2500;
1537a5c72737SRavi Kumar 	}
1538a5c72737SRavi Kumar }
1539a5c72737SRavi Kumar 
1540a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_switch_bp_2500_mode(struct axgbe_port *pdata
1541a5c72737SRavi Kumar 						     __rte_unused)
1542a5c72737SRavi Kumar {
1543a5c72737SRavi Kumar 	return AXGBE_MODE_KX_2500;
1544a5c72737SRavi Kumar }
1545a5c72737SRavi Kumar 
1546a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_switch_bp_mode(struct axgbe_port *pdata)
1547a5c72737SRavi Kumar {
1548a5c72737SRavi Kumar 	/* If we are in KR switch to KX, and vice-versa */
1549a5c72737SRavi Kumar 	switch (axgbe_phy_cur_mode(pdata)) {
1550a5c72737SRavi Kumar 	case AXGBE_MODE_KX_1000:
1551a5c72737SRavi Kumar 		return AXGBE_MODE_KR;
1552a5c72737SRavi Kumar 	case AXGBE_MODE_KR:
1553a5c72737SRavi Kumar 	default:
1554a5c72737SRavi Kumar 		return AXGBE_MODE_KX_1000;
1555a5c72737SRavi Kumar 	}
1556a5c72737SRavi Kumar }
1557a5c72737SRavi Kumar 
1558a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_switch_mode(struct axgbe_port *pdata)
1559a5c72737SRavi Kumar {
1560a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1561a5c72737SRavi Kumar 
1562a5c72737SRavi Kumar 	switch (phy_data->port_mode) {
1563a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE:
1564443ab5aaSSelwin Sebastian 	case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG:
1565a5c72737SRavi Kumar 		return axgbe_phy_switch_bp_mode(pdata);
1566a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE_2500:
1567a5c72737SRavi Kumar 		return axgbe_phy_switch_bp_2500_mode(pdata);
1568a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_T:
1569a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_NBASE_T:
1570a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_T:
1571a5c72737SRavi Kumar 		return axgbe_phy_switch_baset_mode(pdata);
1572a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_X:
1573a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_R:
1574a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_SFP:
1575a5c72737SRavi Kumar 		/* No switching, so just return current mode */
1576a5c72737SRavi Kumar 		return axgbe_phy_cur_mode(pdata);
1577a5c72737SRavi Kumar 	default:
1578a5c72737SRavi Kumar 		return AXGBE_MODE_UNKNOWN;
1579a5c72737SRavi Kumar 	}
1580a5c72737SRavi Kumar }
1581a5c72737SRavi Kumar 
1582a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_basex_mode(struct axgbe_phy_data *phy_data
1583a5c72737SRavi Kumar 						__rte_unused,
1584a5c72737SRavi Kumar 						int speed)
1585a5c72737SRavi Kumar {
1586a5c72737SRavi Kumar 	switch (speed) {
1587a5c72737SRavi Kumar 	case SPEED_1000:
1588a5c72737SRavi Kumar 		return AXGBE_MODE_X;
1589a5c72737SRavi Kumar 	case SPEED_10000:
1590a5c72737SRavi Kumar 		return AXGBE_MODE_KR;
1591a5c72737SRavi Kumar 	default:
1592a5c72737SRavi Kumar 		return AXGBE_MODE_UNKNOWN;
1593a5c72737SRavi Kumar 	}
1594a5c72737SRavi Kumar }
1595a5c72737SRavi Kumar 
1596a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_baset_mode(struct axgbe_phy_data *phy_data
1597a5c72737SRavi Kumar 						__rte_unused,
1598a5c72737SRavi Kumar 						int speed)
1599a5c72737SRavi Kumar {
1600a5c72737SRavi Kumar 	switch (speed) {
16011f9d2d3aSVenkat Kumar Ande 	case SPEED_10:
16021f9d2d3aSVenkat Kumar Ande 		return AXGBE_MODE_SGMII_10;
1603a5c72737SRavi Kumar 	case SPEED_100:
1604a5c72737SRavi Kumar 		return AXGBE_MODE_SGMII_100;
1605a5c72737SRavi Kumar 	case SPEED_1000:
1606a5c72737SRavi Kumar 		return AXGBE_MODE_SGMII_1000;
1607a5c72737SRavi Kumar 	case SPEED_10000:
1608a5c72737SRavi Kumar 		return AXGBE_MODE_KR;
1609a5c72737SRavi Kumar 	default:
1610a5c72737SRavi Kumar 		return AXGBE_MODE_UNKNOWN;
1611a5c72737SRavi Kumar 	}
1612a5c72737SRavi Kumar }
1613a5c72737SRavi Kumar 
1614a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_sfp_mode(struct axgbe_phy_data *phy_data,
1615a5c72737SRavi Kumar 					      int speed)
1616a5c72737SRavi Kumar {
1617a5c72737SRavi Kumar 	switch (speed) {
16181f9d2d3aSVenkat Kumar Ande 	case SPEED_10:
16191f9d2d3aSVenkat Kumar Ande 		return AXGBE_MODE_SGMII_10;
1620a5c72737SRavi Kumar 	case SPEED_100:
1621a5c72737SRavi Kumar 		return AXGBE_MODE_SGMII_100;
1622a5c72737SRavi Kumar 	case SPEED_1000:
1623a5c72737SRavi Kumar 		if (phy_data->sfp_base == AXGBE_SFP_BASE_1000_T)
1624a5c72737SRavi Kumar 			return AXGBE_MODE_SGMII_1000;
1625a5c72737SRavi Kumar 		else
1626a5c72737SRavi Kumar 			return AXGBE_MODE_X;
1627a5c72737SRavi Kumar 	case SPEED_10000:
1628a5c72737SRavi Kumar 	case SPEED_UNKNOWN:
1629a5c72737SRavi Kumar 		return AXGBE_MODE_SFI;
1630a5c72737SRavi Kumar 	default:
1631a5c72737SRavi Kumar 		return AXGBE_MODE_UNKNOWN;
1632a5c72737SRavi Kumar 	}
1633a5c72737SRavi Kumar }
1634a5c72737SRavi Kumar 
1635a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_bp_2500_mode(int speed)
1636a5c72737SRavi Kumar {
1637a5c72737SRavi Kumar 	switch (speed) {
1638a5c72737SRavi Kumar 	case SPEED_2500:
1639a5c72737SRavi Kumar 		return AXGBE_MODE_KX_2500;
1640a5c72737SRavi Kumar 	default:
1641a5c72737SRavi Kumar 		return AXGBE_MODE_UNKNOWN;
1642a5c72737SRavi Kumar 	}
1643a5c72737SRavi Kumar }
1644a5c72737SRavi Kumar 
1645a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_bp_mode(int speed)
1646a5c72737SRavi Kumar {
1647a5c72737SRavi Kumar 	switch (speed) {
1648a5c72737SRavi Kumar 	case SPEED_1000:
1649a5c72737SRavi Kumar 		return AXGBE_MODE_KX_1000;
1650a5c72737SRavi Kumar 	case SPEED_10000:
1651a5c72737SRavi Kumar 		return AXGBE_MODE_KR;
1652a5c72737SRavi Kumar 	default:
1653a5c72737SRavi Kumar 		return AXGBE_MODE_UNKNOWN;
1654a5c72737SRavi Kumar 	}
1655a5c72737SRavi Kumar }
1656a5c72737SRavi Kumar 
1657a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_mode(struct axgbe_port *pdata,
1658a5c72737SRavi Kumar 					  int speed)
1659a5c72737SRavi Kumar {
1660a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1661a5c72737SRavi Kumar 
1662a5c72737SRavi Kumar 	switch (phy_data->port_mode) {
1663a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE:
1664443ab5aaSSelwin Sebastian 	case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG:
1665a5c72737SRavi Kumar 		return axgbe_phy_get_bp_mode(speed);
1666a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE_2500:
1667a5c72737SRavi Kumar 		return axgbe_phy_get_bp_2500_mode(speed);
1668a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_T:
1669a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_NBASE_T:
1670a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_T:
1671a5c72737SRavi Kumar 		return axgbe_phy_get_baset_mode(phy_data, speed);
1672a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_X:
1673a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_R:
1674a5c72737SRavi Kumar 		return axgbe_phy_get_basex_mode(phy_data, speed);
1675a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_SFP:
1676a5c72737SRavi Kumar 		return axgbe_phy_get_sfp_mode(phy_data, speed);
1677a5c72737SRavi Kumar 	default:
1678a5c72737SRavi Kumar 		return AXGBE_MODE_UNKNOWN;
1679a5c72737SRavi Kumar 	}
1680a5c72737SRavi Kumar }
1681a5c72737SRavi Kumar 
1682a5c72737SRavi Kumar static void axgbe_phy_set_mode(struct axgbe_port *pdata, enum axgbe_mode mode)
1683a5c72737SRavi Kumar {
1684a5c72737SRavi Kumar 	switch (mode) {
1685a5c72737SRavi Kumar 	case AXGBE_MODE_KR:
1686a5c72737SRavi Kumar 		axgbe_phy_kr_mode(pdata);
1687a5c72737SRavi Kumar 		break;
1688a5c72737SRavi Kumar 	case AXGBE_MODE_SFI:
1689a5c72737SRavi Kumar 		axgbe_phy_sfi_mode(pdata);
1690a5c72737SRavi Kumar 		break;
1691936e294cSGirish Nandibasappa 	case AXGBE_MODE_KX_2500:
1692936e294cSGirish Nandibasappa 		axgbe_phy_kx_2500_mode(pdata);
1693936e294cSGirish Nandibasappa 		break;
1694936e294cSGirish Nandibasappa 	case AXGBE_MODE_SGMII_1000:
1695936e294cSGirish Nandibasappa 		axgbe_phy_sgmii_1000_mode(pdata);
1696936e294cSGirish Nandibasappa 		break;
16971f9d2d3aSVenkat Kumar Ande 	case AXGBE_MODE_SGMII_10:
16981f9d2d3aSVenkat Kumar Ande 		axgbe_phy_sgmii_10_mode(pdata);
16991f9d2d3aSVenkat Kumar Ande 		break;
1700a5c72737SRavi Kumar 	default:
1701a5c72737SRavi Kumar 		break;
1702a5c72737SRavi Kumar 	}
1703a5c72737SRavi Kumar }
1704a5c72737SRavi Kumar 
1705a5c72737SRavi Kumar static bool axgbe_phy_check_mode(struct axgbe_port *pdata,
1706a5c72737SRavi Kumar 				 enum axgbe_mode mode, u32 advert)
1707a5c72737SRavi Kumar {
1708a5c72737SRavi Kumar 	if (pdata->phy.autoneg == AUTONEG_ENABLE) {
1709a5c72737SRavi Kumar 		if (pdata->phy.advertising & advert)
1710a5c72737SRavi Kumar 			return true;
1711a5c72737SRavi Kumar 	} else {
1712a5c72737SRavi Kumar 		enum axgbe_mode cur_mode;
1713a5c72737SRavi Kumar 
1714a5c72737SRavi Kumar 		cur_mode = axgbe_phy_get_mode(pdata, pdata->phy.speed);
1715a5c72737SRavi Kumar 		if (cur_mode == mode)
1716a5c72737SRavi Kumar 			return true;
1717a5c72737SRavi Kumar 	}
1718a5c72737SRavi Kumar 
1719a5c72737SRavi Kumar 	return false;
1720a5c72737SRavi Kumar }
1721a5c72737SRavi Kumar 
1722a5c72737SRavi Kumar static bool axgbe_phy_use_basex_mode(struct axgbe_port *pdata,
1723a5c72737SRavi Kumar 				     enum axgbe_mode mode)
1724a5c72737SRavi Kumar {
1725a5c72737SRavi Kumar 	switch (mode) {
1726a5c72737SRavi Kumar 	case AXGBE_MODE_X:
1727a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1728a5c72737SRavi Kumar 					    ADVERTISED_1000baseT_Full);
1729a5c72737SRavi Kumar 	case AXGBE_MODE_KR:
1730a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1731a5c72737SRavi Kumar 					    ADVERTISED_10000baseT_Full);
1732a5c72737SRavi Kumar 	default:
1733a5c72737SRavi Kumar 		return false;
1734a5c72737SRavi Kumar 	}
1735a5c72737SRavi Kumar }
1736a5c72737SRavi Kumar 
1737a5c72737SRavi Kumar static bool axgbe_phy_use_baset_mode(struct axgbe_port *pdata,
1738a5c72737SRavi Kumar 				     enum axgbe_mode mode)
1739a5c72737SRavi Kumar {
1740a5c72737SRavi Kumar 	switch (mode) {
17411f9d2d3aSVenkat Kumar Ande 	case AXGBE_MODE_SGMII_10:
17421f9d2d3aSVenkat Kumar Ande 		return axgbe_phy_check_mode(pdata, mode,
17431f9d2d3aSVenkat Kumar Ande 					    ADVERTISED_10baseT_Full);
1744a5c72737SRavi Kumar 	case AXGBE_MODE_SGMII_100:
1745a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1746a5c72737SRavi Kumar 					    ADVERTISED_100baseT_Full);
1747a5c72737SRavi Kumar 	case AXGBE_MODE_SGMII_1000:
1748a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1749a5c72737SRavi Kumar 					    ADVERTISED_1000baseT_Full);
1750a5c72737SRavi Kumar 	case AXGBE_MODE_KR:
1751a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1752a5c72737SRavi Kumar 					    ADVERTISED_10000baseT_Full);
1753a5c72737SRavi Kumar 	default:
1754a5c72737SRavi Kumar 		return false;
1755a5c72737SRavi Kumar 	}
1756a5c72737SRavi Kumar }
1757a5c72737SRavi Kumar 
1758a5c72737SRavi Kumar static bool axgbe_phy_use_sfp_mode(struct axgbe_port *pdata,
1759a5c72737SRavi Kumar 				   enum axgbe_mode mode)
1760a5c72737SRavi Kumar {
1761a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1762a5c72737SRavi Kumar 
1763a5c72737SRavi Kumar 	switch (mode) {
1764a5c72737SRavi Kumar 	case AXGBE_MODE_X:
1765a5c72737SRavi Kumar 		if (phy_data->sfp_base == AXGBE_SFP_BASE_1000_T)
1766a5c72737SRavi Kumar 			return false;
1767a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1768a5c72737SRavi Kumar 					    ADVERTISED_1000baseT_Full);
17691f9d2d3aSVenkat Kumar Ande 	case AXGBE_MODE_SGMII_10:
17701f9d2d3aSVenkat Kumar Ande 		if (phy_data->sfp_base != AXGBE_SFP_BASE_1000_T)
17711f9d2d3aSVenkat Kumar Ande 			return false;
17721f9d2d3aSVenkat Kumar Ande 		return axgbe_phy_check_mode(pdata, mode,
17731f9d2d3aSVenkat Kumar Ande 					    ADVERTISED_10baseT_Full);
1774a5c72737SRavi Kumar 	case AXGBE_MODE_SGMII_100:
1775a5c72737SRavi Kumar 		if (phy_data->sfp_base != AXGBE_SFP_BASE_1000_T)
1776a5c72737SRavi Kumar 			return false;
1777a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1778a5c72737SRavi Kumar 					    ADVERTISED_100baseT_Full);
1779a5c72737SRavi Kumar 	case AXGBE_MODE_SGMII_1000:
1780a5c72737SRavi Kumar 		if (phy_data->sfp_base != AXGBE_SFP_BASE_1000_T)
1781a5c72737SRavi Kumar 			return false;
1782a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1783a5c72737SRavi Kumar 					    ADVERTISED_1000baseT_Full);
1784a5c72737SRavi Kumar 	case AXGBE_MODE_SFI:
1785a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1786a5c72737SRavi Kumar 					    ADVERTISED_10000baseT_Full);
1787a5c72737SRavi Kumar 	default:
1788a5c72737SRavi Kumar 		return false;
1789a5c72737SRavi Kumar 	}
1790a5c72737SRavi Kumar }
1791a5c72737SRavi Kumar 
1792a5c72737SRavi Kumar static bool axgbe_phy_use_bp_2500_mode(struct axgbe_port *pdata,
1793a5c72737SRavi Kumar 				       enum axgbe_mode mode)
1794a5c72737SRavi Kumar {
1795a5c72737SRavi Kumar 	switch (mode) {
1796a5c72737SRavi Kumar 	case AXGBE_MODE_KX_2500:
1797a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1798a5c72737SRavi Kumar 					    ADVERTISED_2500baseX_Full);
1799a5c72737SRavi Kumar 	default:
1800a5c72737SRavi Kumar 		return false;
1801a5c72737SRavi Kumar 	}
1802a5c72737SRavi Kumar }
1803a5c72737SRavi Kumar 
1804a5c72737SRavi Kumar static bool axgbe_phy_use_bp_mode(struct axgbe_port *pdata,
1805a5c72737SRavi Kumar 				  enum axgbe_mode mode)
1806a5c72737SRavi Kumar {
1807a5c72737SRavi Kumar 	switch (mode) {
1808a5c72737SRavi Kumar 	case AXGBE_MODE_KX_1000:
1809a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1810a5c72737SRavi Kumar 					    ADVERTISED_1000baseKX_Full);
1811a5c72737SRavi Kumar 	case AXGBE_MODE_KR:
1812a5c72737SRavi Kumar 		return axgbe_phy_check_mode(pdata, mode,
1813a5c72737SRavi Kumar 					    ADVERTISED_10000baseKR_Full);
1814a5c72737SRavi Kumar 	default:
1815a5c72737SRavi Kumar 		return false;
1816a5c72737SRavi Kumar 	}
1817a5c72737SRavi Kumar }
1818a5c72737SRavi Kumar 
1819a5c72737SRavi Kumar static bool axgbe_phy_use_mode(struct axgbe_port *pdata, enum axgbe_mode mode)
1820a5c72737SRavi Kumar {
1821a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1822a5c72737SRavi Kumar 
1823a5c72737SRavi Kumar 	switch (phy_data->port_mode) {
1824a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE:
1825443ab5aaSSelwin Sebastian 	case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG:
1826a5c72737SRavi Kumar 		return axgbe_phy_use_bp_mode(pdata, mode);
1827a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE_2500:
1828a5c72737SRavi Kumar 		return axgbe_phy_use_bp_2500_mode(pdata, mode);
1829a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_T:
1830a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_NBASE_T:
1831a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_T:
1832a5c72737SRavi Kumar 		return axgbe_phy_use_baset_mode(pdata, mode);
1833a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_X:
1834a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_R:
1835a5c72737SRavi Kumar 		return axgbe_phy_use_basex_mode(pdata, mode);
1836a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_SFP:
1837a5c72737SRavi Kumar 		return axgbe_phy_use_sfp_mode(pdata, mode);
1838a5c72737SRavi Kumar 	default:
1839a5c72737SRavi Kumar 		return false;
1840a5c72737SRavi Kumar 	}
1841a5c72737SRavi Kumar }
1842a5c72737SRavi Kumar 
1843a5c72737SRavi Kumar static int axgbe_phy_link_status(struct axgbe_port *pdata, int *an_restart)
1844a5c72737SRavi Kumar {
1845a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1846a5c72737SRavi Kumar 	unsigned int reg;
1847a5c72737SRavi Kumar 
1848a5c72737SRavi Kumar 	*an_restart = 0;
1849a5c72737SRavi Kumar 
1850a5c72737SRavi Kumar 	if (phy_data->port_mode == AXGBE_PORT_MODE_SFP) {
1851a5c72737SRavi Kumar 		/* Check SFP signals */
1852a5c72737SRavi Kumar 		axgbe_phy_sfp_detect(pdata);
1853a5c72737SRavi Kumar 
1854a5c72737SRavi Kumar 		if (phy_data->sfp_changed) {
1855a5c72737SRavi Kumar 			*an_restart = 1;
1856a5c72737SRavi Kumar 			return 0;
1857a5c72737SRavi Kumar 		}
1858a5c72737SRavi Kumar 
18596c04898fSVenkat Kumar Ande 		if (phy_data->sfp_mod_absent || phy_data->sfp_rx_los) {
18606c04898fSVenkat Kumar Ande 			if (pdata->en_rx_adap)
18616c04898fSVenkat Kumar Ande 				pdata->rx_adapt_done = false;
1862a5c72737SRavi Kumar 			return 0;
1863a5c72737SRavi Kumar 		}
18646c04898fSVenkat Kumar Ande 	}
1865a5c72737SRavi Kumar 
1866a5c72737SRavi Kumar 	/* Link status is latched low, so read once to clear
1867a5c72737SRavi Kumar 	 * and then read again to get current state
1868a5c72737SRavi Kumar 	 */
1869a5c72737SRavi Kumar 	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
1870a5c72737SRavi Kumar 	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
18716c04898fSVenkat Kumar Ande 
18726c04898fSVenkat Kumar Ande 	if (pdata->en_rx_adap) {
18736c04898fSVenkat Kumar Ande 		/* if the link is available and adaptation is done,
18746c04898fSVenkat Kumar Ande 		 * declare link up
18756c04898fSVenkat Kumar Ande 		 */
18766c04898fSVenkat Kumar Ande 		if ((reg & MDIO_STAT1_LSTATUS) && pdata->rx_adapt_done)
18776c04898fSVenkat Kumar Ande 			return 1;
18786c04898fSVenkat Kumar Ande 		/* If either link is not available or adaptation is not done,
18796c04898fSVenkat Kumar Ande 		 * retrigger the adaptation logic. (if the mode is not set,
18806c04898fSVenkat Kumar Ande 		 * then issue mailbox command first)
18816c04898fSVenkat Kumar Ande 		 */
18826c04898fSVenkat Kumar Ande 		if (pdata->mode_set) {
18836c04898fSVenkat Kumar Ande 			axgbe_phy_rx_adaptation(pdata);
18846c04898fSVenkat Kumar Ande 		} else {
18856c04898fSVenkat Kumar Ande 			pdata->rx_adapt_done = false;
18866c04898fSVenkat Kumar Ande 			axgbe_phy_set_mode(pdata, phy_data->cur_mode);
18876c04898fSVenkat Kumar Ande 		}
18886c04898fSVenkat Kumar Ande 
18896c04898fSVenkat Kumar Ande 		/* check again for the link and adaptation status */
18906c04898fSVenkat Kumar Ande 		reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
18916c04898fSVenkat Kumar Ande 		if ((reg & MDIO_STAT1_LSTATUS) && pdata->rx_adapt_done)
18926c04898fSVenkat Kumar Ande 			return 1;
18936c04898fSVenkat Kumar Ande 	} else if (reg & MDIO_STAT1_LSTATUS)
1894a5c72737SRavi Kumar 		return 1;
1895a5c72737SRavi Kumar 
1896edf46325SVenkat Kumar Ande 	if (pdata->phy.autoneg == AUTONEG_ENABLE &&
1897edf46325SVenkat Kumar Ande 			phy_data->port_mode == AXGBE_PORT_MODE_BACKPLANE) {
1898edf46325SVenkat Kumar Ande 		if (rte_bit_relaxed_get32(AXGBE_LINK_INIT, &pdata->dev_state)) {
1899edf46325SVenkat Kumar Ande 			*an_restart = 1;
1900edf46325SVenkat Kumar Ande 		}
1901edf46325SVenkat Kumar Ande 	}
1902edf46325SVenkat Kumar Ande 
1903a5c72737SRavi Kumar 	/* No link, attempt a receiver reset cycle */
1904e82b0fe0SVenkat Kumar Ande 	if (pdata->vdata->enable_rrc && phy_data->rrc_count++) {
1905a5c72737SRavi Kumar 		phy_data->rrc_count = 0;
1906a5c72737SRavi Kumar 		axgbe_phy_rrc(pdata);
1907a5c72737SRavi Kumar 	}
1908a5c72737SRavi Kumar 
1909a5c72737SRavi Kumar 	return 0;
1910a5c72737SRavi Kumar }
1911a5c72737SRavi Kumar 
19124ac7516bSRavi Kumar static void axgbe_phy_sfp_gpio_setup(struct axgbe_port *pdata)
19134ac7516bSRavi Kumar {
19144ac7516bSRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
19154ac7516bSRavi Kumar 
19164ac7516bSRavi Kumar 	phy_data->sfp_gpio_address = AXGBE_GPIO_ADDRESS_PCA9555 +
1917a3ec01b4SVenkat Kumar Ande 		XP_GET_BITS(pdata->pp3, XP_PROP_3, GPIO_ADDR);
19184ac7516bSRavi Kumar 
1919a3ec01b4SVenkat Kumar Ande 	phy_data->sfp_gpio_mask = XP_GET_BITS(pdata->pp3, XP_PROP_3, GPIO_MASK);
19204ac7516bSRavi Kumar 
1921a3ec01b4SVenkat Kumar Ande 	phy_data->sfp_gpio_rx_los = XP_GET_BITS(pdata->pp3, XP_PROP_3,
19224ac7516bSRavi Kumar 						GPIO_RX_LOS);
1923a3ec01b4SVenkat Kumar Ande 	phy_data->sfp_gpio_tx_fault = XP_GET_BITS(pdata->pp3, XP_PROP_3,
19244ac7516bSRavi Kumar 						  GPIO_TX_FAULT);
1925a3ec01b4SVenkat Kumar Ande 	phy_data->sfp_gpio_mod_absent = XP_GET_BITS(pdata->pp3, XP_PROP_3,
19264ac7516bSRavi Kumar 						    GPIO_MOD_ABS);
1927a3ec01b4SVenkat Kumar Ande 	phy_data->sfp_gpio_rate_select = XP_GET_BITS(pdata->pp3, XP_PROP_3,
19284ac7516bSRavi Kumar 						     GPIO_RATE_SELECT);
19294ac7516bSRavi Kumar }
19304ac7516bSRavi Kumar 
19314ac7516bSRavi Kumar static void axgbe_phy_sfp_comm_setup(struct axgbe_port *pdata)
19324ac7516bSRavi Kumar {
19334ac7516bSRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
1934a3ec01b4SVenkat Kumar Ande 	unsigned int mux_addr_hi, mux_addr_lo;
19354ac7516bSRavi Kumar 
1936a3ec01b4SVenkat Kumar Ande 	mux_addr_hi = XP_GET_BITS(pdata->pp4, XP_PROP_4, MUX_ADDR_HI);
1937a3ec01b4SVenkat Kumar Ande 	mux_addr_lo = XP_GET_BITS(pdata->pp4, XP_PROP_4, MUX_ADDR_LO);
19384ac7516bSRavi Kumar 	if (mux_addr_lo == AXGBE_SFP_DIRECT)
19394ac7516bSRavi Kumar 		return;
19404ac7516bSRavi Kumar 
19414ac7516bSRavi Kumar 	phy_data->sfp_comm = AXGBE_SFP_COMM_PCA9545;
19424ac7516bSRavi Kumar 	phy_data->sfp_mux_address = (mux_addr_hi << 2) + mux_addr_lo;
1943a3ec01b4SVenkat Kumar Ande 	phy_data->sfp_mux_channel = XP_GET_BITS(pdata->pp4, XP_PROP_4, MUX_CHAN);
19444ac7516bSRavi Kumar }
19454ac7516bSRavi Kumar 
19464ac7516bSRavi Kumar static void axgbe_phy_sfp_setup(struct axgbe_port *pdata)
19474ac7516bSRavi Kumar {
19484ac7516bSRavi Kumar 	axgbe_phy_sfp_comm_setup(pdata);
19494ac7516bSRavi Kumar 	axgbe_phy_sfp_gpio_setup(pdata);
19504ac7516bSRavi Kumar }
19514ac7516bSRavi Kumar 
19524ac7516bSRavi Kumar static bool axgbe_phy_redrv_error(struct axgbe_phy_data *phy_data)
19534ac7516bSRavi Kumar {
19544ac7516bSRavi Kumar 	if (!phy_data->redrv)
19554ac7516bSRavi Kumar 		return false;
19564ac7516bSRavi Kumar 
19574ac7516bSRavi Kumar 	if (phy_data->redrv_if >= AXGBE_PHY_REDRV_IF_MAX)
19584ac7516bSRavi Kumar 		return true;
19594ac7516bSRavi Kumar 
19604ac7516bSRavi Kumar 	switch (phy_data->redrv_model) {
19614ac7516bSRavi Kumar 	case AXGBE_PHY_REDRV_MODEL_4223:
19624ac7516bSRavi Kumar 		if (phy_data->redrv_lane > 3)
19634ac7516bSRavi Kumar 			return true;
19644ac7516bSRavi Kumar 		break;
19654ac7516bSRavi Kumar 	case AXGBE_PHY_REDRV_MODEL_4227:
19664ac7516bSRavi Kumar 		if (phy_data->redrv_lane > 1)
19674ac7516bSRavi Kumar 			return true;
19684ac7516bSRavi Kumar 		break;
19694ac7516bSRavi Kumar 	default:
19704ac7516bSRavi Kumar 		return true;
19714ac7516bSRavi Kumar 	}
19724ac7516bSRavi Kumar 
19734ac7516bSRavi Kumar 	return false;
19744ac7516bSRavi Kumar }
19754ac7516bSRavi Kumar 
19764ac7516bSRavi Kumar static int axgbe_phy_mdio_reset_setup(struct axgbe_port *pdata)
19774ac7516bSRavi Kumar {
19784ac7516bSRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
19794ac7516bSRavi Kumar 
19804ac7516bSRavi Kumar 	if (phy_data->conn_type != AXGBE_CONN_TYPE_MDIO)
19814ac7516bSRavi Kumar 		return 0;
1982a3ec01b4SVenkat Kumar Ande 
1983a3ec01b4SVenkat Kumar Ande 	phy_data->mdio_reset = XP_GET_BITS(pdata->pp3, XP_PROP_3, MDIO_RESET);
19844ac7516bSRavi Kumar 	switch (phy_data->mdio_reset) {
19854ac7516bSRavi Kumar 	case AXGBE_MDIO_RESET_NONE:
19864ac7516bSRavi Kumar 	case AXGBE_MDIO_RESET_I2C_GPIO:
19874ac7516bSRavi Kumar 	case AXGBE_MDIO_RESET_INT_GPIO:
19884ac7516bSRavi Kumar 		break;
19894ac7516bSRavi Kumar 	default:
1990*e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(ERR, "unsupported MDIO reset (%#x)",
19914ac7516bSRavi Kumar 			    phy_data->mdio_reset);
19924ac7516bSRavi Kumar 		return -EINVAL;
19934ac7516bSRavi Kumar 	}
19944ac7516bSRavi Kumar 	if (phy_data->mdio_reset == AXGBE_MDIO_RESET_I2C_GPIO) {
19954ac7516bSRavi Kumar 		phy_data->mdio_reset_addr = AXGBE_GPIO_ADDRESS_PCA9555 +
1996a3ec01b4SVenkat Kumar Ande 			XP_GET_BITS(pdata->pp3, XP_PROP_3,
19974ac7516bSRavi Kumar 				    MDIO_RESET_I2C_ADDR);
1998a3ec01b4SVenkat Kumar Ande 		phy_data->mdio_reset_gpio = XP_GET_BITS(pdata->pp3, XP_PROP_3,
19994ac7516bSRavi Kumar 							MDIO_RESET_I2C_GPIO);
20004ac7516bSRavi Kumar 	} else if (phy_data->mdio_reset == AXGBE_MDIO_RESET_INT_GPIO) {
2001a3ec01b4SVenkat Kumar Ande 		phy_data->mdio_reset_gpio = XP_GET_BITS(pdata->pp3, XP_PROP_3,
20024ac7516bSRavi Kumar 							MDIO_RESET_INT_GPIO);
20034ac7516bSRavi Kumar 	}
20044ac7516bSRavi Kumar 
20054ac7516bSRavi Kumar 	return 0;
20064ac7516bSRavi Kumar }
20074ac7516bSRavi Kumar 
20084ac7516bSRavi Kumar static bool axgbe_phy_port_mode_mismatch(struct axgbe_port *pdata)
20094ac7516bSRavi Kumar {
20104ac7516bSRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
20111f9d2d3aSVenkat Kumar Ande 	unsigned int ver;
20121f9d2d3aSVenkat Kumar Ande 
20134d3690abSVenkat Kumar Ande 	/* 10 Mbps speed is supported in ver 21H and ver >= 30H */
20141f9d2d3aSVenkat Kumar Ande 	ver = AXGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER);
20154d3690abSVenkat Kumar Ande 	if ((ver < 0x30 && ver != 0x21) && phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10)
20161f9d2d3aSVenkat Kumar Ande 		return true;
20174ac7516bSRavi Kumar 
20184ac7516bSRavi Kumar 	switch (phy_data->port_mode) {
20194ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE:
2020443ab5aaSSelwin Sebastian 	case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG:
20214ac7516bSRavi Kumar 		if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) ||
20224ac7516bSRavi Kumar 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000))
20234ac7516bSRavi Kumar 			return false;
20244ac7516bSRavi Kumar 		break;
20254ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE_2500:
20264ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500)
20274ac7516bSRavi Kumar 			return false;
20284ac7516bSRavi Kumar 		break;
20294ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_T:
20301f9d2d3aSVenkat Kumar Ande 		if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10)  ||
20311f9d2d3aSVenkat Kumar Ande 			(phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) ||
20324ac7516bSRavi Kumar 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000))
20334ac7516bSRavi Kumar 			return false;
20344ac7516bSRavi Kumar 		break;
20354ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_X:
20364ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000)
20374ac7516bSRavi Kumar 			return false;
20384ac7516bSRavi Kumar 		break;
20394ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_NBASE_T:
20401f9d2d3aSVenkat Kumar Ande 		if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10)  ||
20411f9d2d3aSVenkat Kumar Ande 			(phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) ||
20424ac7516bSRavi Kumar 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) ||
20434ac7516bSRavi Kumar 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500))
20444ac7516bSRavi Kumar 			return false;
20454ac7516bSRavi Kumar 		break;
20464ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_T:
20471f9d2d3aSVenkat Kumar Ande 		if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10)  ||
20481f9d2d3aSVenkat Kumar Ande 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) ||
20494ac7516bSRavi Kumar 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) ||
2050d7344a7bSVenkat Kumar Ande 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500) ||
20514ac7516bSRavi Kumar 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000))
20524ac7516bSRavi Kumar 			return false;
20534ac7516bSRavi Kumar 		break;
20544ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_R:
20554ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000)
20564ac7516bSRavi Kumar 			return false;
20574ac7516bSRavi Kumar 		break;
20584ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_SFP:
20591f9d2d3aSVenkat Kumar Ande 		if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10)  ||
20601f9d2d3aSVenkat Kumar Ande 			(phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) ||
20614ac7516bSRavi Kumar 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) ||
20624ac7516bSRavi Kumar 		    (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000))
20634ac7516bSRavi Kumar 			return false;
20644ac7516bSRavi Kumar 		break;
20654ac7516bSRavi Kumar 	default:
20664ac7516bSRavi Kumar 		break;
20674ac7516bSRavi Kumar 	}
20684ac7516bSRavi Kumar 
20694ac7516bSRavi Kumar 	return true;
20704ac7516bSRavi Kumar }
20714ac7516bSRavi Kumar 
20724ac7516bSRavi Kumar static bool axgbe_phy_conn_type_mismatch(struct axgbe_port *pdata)
20734ac7516bSRavi Kumar {
20744ac7516bSRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
20754ac7516bSRavi Kumar 
20764ac7516bSRavi Kumar 	switch (phy_data->port_mode) {
20774ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE:
2078443ab5aaSSelwin Sebastian 	case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG:
20794ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE_2500:
20804ac7516bSRavi Kumar 		if (phy_data->conn_type == AXGBE_CONN_TYPE_BACKPLANE)
20814ac7516bSRavi Kumar 			return false;
20824ac7516bSRavi Kumar 		break;
20834ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_T:
20844ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_X:
20854ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_NBASE_T:
20864ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_T:
20874ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_R:
20884ac7516bSRavi Kumar 		if (phy_data->conn_type == AXGBE_CONN_TYPE_MDIO)
20894ac7516bSRavi Kumar 			return false;
20904ac7516bSRavi Kumar 		break;
20914ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_SFP:
20924ac7516bSRavi Kumar 		if (phy_data->conn_type == AXGBE_CONN_TYPE_SFP)
20934ac7516bSRavi Kumar 			return false;
20944ac7516bSRavi Kumar 		break;
20954ac7516bSRavi Kumar 	default:
20964ac7516bSRavi Kumar 		break;
20974ac7516bSRavi Kumar 	}
20984ac7516bSRavi Kumar 
20994ac7516bSRavi Kumar 	return true;
21004ac7516bSRavi Kumar }
21014ac7516bSRavi Kumar 
21024ac7516bSRavi Kumar static bool axgbe_phy_port_enabled(struct axgbe_port *pdata)
21034ac7516bSRavi Kumar {
2104a3ec01b4SVenkat Kumar Ande 	if (!XP_GET_BITS(pdata->pp0, XP_PROP_0, PORT_SPEEDS))
21054ac7516bSRavi Kumar 		return false;
2106a3ec01b4SVenkat Kumar Ande 	if (!XP_GET_BITS(pdata->pp0, XP_PROP_0, CONN_TYPE))
21074ac7516bSRavi Kumar 		return false;
21084ac7516bSRavi Kumar 
21094ac7516bSRavi Kumar 	return true;
21104ac7516bSRavi Kumar }
21114ac7516bSRavi Kumar 
211200072056SRavi Kumar static void axgbe_phy_cdr_track(struct axgbe_port *pdata)
211300072056SRavi Kumar {
211400072056SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
211500072056SRavi Kumar 
211600072056SRavi Kumar 	if (!pdata->vdata->an_cdr_workaround)
211700072056SRavi Kumar 		return;
211800072056SRavi Kumar 
211900072056SRavi Kumar 	if (!phy_data->phy_cdr_notrack)
212000072056SRavi Kumar 		return;
212100072056SRavi Kumar 
212200072056SRavi Kumar 	rte_delay_us(phy_data->phy_cdr_delay + 400);
212300072056SRavi Kumar 
212400072056SRavi Kumar 	XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_CDR_CONTROL,
212500072056SRavi Kumar 			 AXGBE_PMA_CDR_TRACK_EN_MASK,
212600072056SRavi Kumar 			 AXGBE_PMA_CDR_TRACK_EN_ON);
212700072056SRavi Kumar 
212800072056SRavi Kumar 	phy_data->phy_cdr_notrack = 0;
212900072056SRavi Kumar }
213000072056SRavi Kumar 
213100072056SRavi Kumar static void axgbe_phy_cdr_notrack(struct axgbe_port *pdata)
213200072056SRavi Kumar {
213300072056SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
213400072056SRavi Kumar 
213500072056SRavi Kumar 	if (!pdata->vdata->an_cdr_workaround)
213600072056SRavi Kumar 		return;
213700072056SRavi Kumar 
213800072056SRavi Kumar 	if (phy_data->phy_cdr_notrack)
213900072056SRavi Kumar 		return;
214000072056SRavi Kumar 
214100072056SRavi Kumar 	XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_CDR_CONTROL,
214200072056SRavi Kumar 			 AXGBE_PMA_CDR_TRACK_EN_MASK,
214300072056SRavi Kumar 			 AXGBE_PMA_CDR_TRACK_EN_OFF);
214400072056SRavi Kumar 
214500072056SRavi Kumar 	axgbe_phy_rrc(pdata);
214600072056SRavi Kumar 
214700072056SRavi Kumar 	phy_data->phy_cdr_notrack = 1;
214800072056SRavi Kumar }
214900072056SRavi Kumar 
215000072056SRavi Kumar static void axgbe_phy_kr_training_post(struct axgbe_port *pdata)
215100072056SRavi Kumar {
215200072056SRavi Kumar 	if (!pdata->cdr_track_early)
215300072056SRavi Kumar 		axgbe_phy_cdr_track(pdata);
215400072056SRavi Kumar }
215500072056SRavi Kumar 
215600072056SRavi Kumar static void axgbe_phy_kr_training_pre(struct axgbe_port *pdata)
215700072056SRavi Kumar {
215800072056SRavi Kumar 	if (pdata->cdr_track_early)
215900072056SRavi Kumar 		axgbe_phy_cdr_track(pdata);
216000072056SRavi Kumar }
216100072056SRavi Kumar 
216200072056SRavi Kumar static void axgbe_phy_an_post(struct axgbe_port *pdata)
216300072056SRavi Kumar {
216400072056SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
216500072056SRavi Kumar 
216600072056SRavi Kumar 	switch (pdata->an_mode) {
216700072056SRavi Kumar 	case AXGBE_AN_MODE_CL73:
216800072056SRavi Kumar 	case AXGBE_AN_MODE_CL73_REDRV:
216900072056SRavi Kumar 		if (phy_data->cur_mode != AXGBE_MODE_KR)
217000072056SRavi Kumar 			break;
217100072056SRavi Kumar 
217200072056SRavi Kumar 		axgbe_phy_cdr_track(pdata);
217300072056SRavi Kumar 
217400072056SRavi Kumar 		switch (pdata->an_result) {
217500072056SRavi Kumar 		case AXGBE_AN_READY:
217600072056SRavi Kumar 		case AXGBE_AN_COMPLETE:
217700072056SRavi Kumar 			break;
217800072056SRavi Kumar 		default:
217900072056SRavi Kumar 			if (phy_data->phy_cdr_delay < AXGBE_CDR_DELAY_MAX)
218000072056SRavi Kumar 				phy_data->phy_cdr_delay += AXGBE_CDR_DELAY_INC;
218100072056SRavi Kumar 			break;
218200072056SRavi Kumar 		}
218300072056SRavi Kumar 		break;
218400072056SRavi Kumar 	default:
218500072056SRavi Kumar 		break;
218600072056SRavi Kumar 	}
218700072056SRavi Kumar }
218800072056SRavi Kumar 
218900072056SRavi Kumar static void axgbe_phy_an_pre(struct axgbe_port *pdata)
219000072056SRavi Kumar {
219100072056SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
219200072056SRavi Kumar 
219300072056SRavi Kumar 	switch (pdata->an_mode) {
219400072056SRavi Kumar 	case AXGBE_AN_MODE_CL73:
219500072056SRavi Kumar 	case AXGBE_AN_MODE_CL73_REDRV:
219600072056SRavi Kumar 		if (phy_data->cur_mode != AXGBE_MODE_KR)
219700072056SRavi Kumar 			break;
219800072056SRavi Kumar 
219900072056SRavi Kumar 		axgbe_phy_cdr_notrack(pdata);
220000072056SRavi Kumar 		break;
220100072056SRavi Kumar 	default:
220200072056SRavi Kumar 		break;
220300072056SRavi Kumar 	}
220400072056SRavi Kumar }
220500072056SRavi Kumar 
2206a5c72737SRavi Kumar static void axgbe_phy_stop(struct axgbe_port *pdata)
2207a5c72737SRavi Kumar {
2208a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
2209a5c72737SRavi Kumar 
2210a5c72737SRavi Kumar 	/* Reset SFP data */
2211a5c72737SRavi Kumar 	axgbe_phy_sfp_reset(phy_data);
2212a5c72737SRavi Kumar 	axgbe_phy_sfp_mod_absent(pdata);
2213a5c72737SRavi Kumar 
221400072056SRavi Kumar 	/* Reset CDR support */
221500072056SRavi Kumar 	axgbe_phy_cdr_track(pdata);
221600072056SRavi Kumar 
2217a5c72737SRavi Kumar 	/* Power off the PHY */
2218a5c72737SRavi Kumar 	axgbe_phy_power_off(pdata);
2219a5c72737SRavi Kumar 
2220a5c72737SRavi Kumar 	/* Stop the I2C controller */
2221a5c72737SRavi Kumar 	pdata->i2c_if.i2c_stop(pdata);
2222a5c72737SRavi Kumar }
2223a5c72737SRavi Kumar 
2224a5c72737SRavi Kumar static int axgbe_phy_start(struct axgbe_port *pdata)
2225a5c72737SRavi Kumar {
2226a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
2227a5c72737SRavi Kumar 	int ret;
2228a5c72737SRavi Kumar 
2229a5c72737SRavi Kumar 	/* Start the I2C controller */
2230a5c72737SRavi Kumar 	ret = pdata->i2c_if.i2c_start(pdata);
2231a5c72737SRavi Kumar 	if (ret)
2232a5c72737SRavi Kumar 		return ret;
2233a5c72737SRavi Kumar 
2234a5c72737SRavi Kumar 	/* Start in highest supported mode */
2235a5c72737SRavi Kumar 	axgbe_phy_set_mode(pdata, phy_data->start_mode);
2236a5c72737SRavi Kumar 
223700072056SRavi Kumar 	/* Reset CDR support */
223800072056SRavi Kumar 	axgbe_phy_cdr_track(pdata);
223900072056SRavi Kumar 
2240a5c72737SRavi Kumar 	/* After starting the I2C controller, we can check for an SFP */
2241a5c72737SRavi Kumar 	switch (phy_data->port_mode) {
2242a5c72737SRavi Kumar 	case AXGBE_PORT_MODE_SFP:
2243a5c72737SRavi Kumar 		axgbe_phy_sfp_detect(pdata);
2244a5c72737SRavi Kumar 		break;
2245a5c72737SRavi Kumar 	default:
2246a5c72737SRavi Kumar 		break;
2247a5c72737SRavi Kumar 	}
2248102b6ec3SGirish Nandibasappa 	pdata->phy.advertising &= axgbe_phy_an_advertising(pdata);
2249a5c72737SRavi Kumar 
2250a5c72737SRavi Kumar 	return ret;
2251a5c72737SRavi Kumar }
2252a5c72737SRavi Kumar 
2253a5c72737SRavi Kumar static int axgbe_phy_reset(struct axgbe_port *pdata)
2254a5c72737SRavi Kumar {
2255a5c72737SRavi Kumar 	struct axgbe_phy_data *phy_data = pdata->phy_data;
2256a5c72737SRavi Kumar 	enum axgbe_mode cur_mode;
2257a5c72737SRavi Kumar 
2258a5c72737SRavi Kumar 	/* Reset by power cycling the PHY */
2259a5c72737SRavi Kumar 	cur_mode = phy_data->cur_mode;
2260a5c72737SRavi Kumar 	axgbe_phy_power_off(pdata);
2261a5c72737SRavi Kumar 	/* First time reset is done with passed unknown mode*/
2262a5c72737SRavi Kumar 	axgbe_phy_set_mode(pdata, cur_mode);
2263a5c72737SRavi Kumar 	return 0;
2264a5c72737SRavi Kumar }
2265a5c72737SRavi Kumar 
22664ac7516bSRavi Kumar static int axgbe_phy_init(struct axgbe_port *pdata)
22674ac7516bSRavi Kumar {
22684ac7516bSRavi Kumar 	struct axgbe_phy_data *phy_data;
22694ac7516bSRavi Kumar 	int ret;
22704ac7516bSRavi Kumar 
22714ac7516bSRavi Kumar 	/* Check if enabled */
22724ac7516bSRavi Kumar 	if (!axgbe_phy_port_enabled(pdata)) {
2273*e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(ERR, "device is not enabled");
22744ac7516bSRavi Kumar 		return -ENODEV;
22754ac7516bSRavi Kumar 	}
22764ac7516bSRavi Kumar 
22774ac7516bSRavi Kumar 	/* Initialize the I2C controller */
22784ac7516bSRavi Kumar 	ret = pdata->i2c_if.i2c_init(pdata);
22794ac7516bSRavi Kumar 	if (ret)
22804ac7516bSRavi Kumar 		return ret;
22814ac7516bSRavi Kumar 
22824ac7516bSRavi Kumar 	phy_data = rte_zmalloc("phy_data memory", sizeof(*phy_data), 0);
22834ac7516bSRavi Kumar 	if (!phy_data) {
2284*e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(ERR, "phy_data allocation failed");
22854ac7516bSRavi Kumar 		return -ENOMEM;
22864ac7516bSRavi Kumar 	}
22874ac7516bSRavi Kumar 	pdata->phy_data = phy_data;
22884ac7516bSRavi Kumar 
2289a3ec01b4SVenkat Kumar Ande 	phy_data->port_mode = XP_GET_BITS(pdata->pp0, XP_PROP_0, PORT_MODE);
2290a3ec01b4SVenkat Kumar Ande 	phy_data->port_id = XP_GET_BITS(pdata->pp0, XP_PROP_0, PORT_ID);
2291a3ec01b4SVenkat Kumar Ande 	phy_data->port_speeds = XP_GET_BITS(pdata->pp0, XP_PROP_0, PORT_SPEEDS);
2292a3ec01b4SVenkat Kumar Ande 	phy_data->conn_type = XP_GET_BITS(pdata->pp0, XP_PROP_0, CONN_TYPE);
2293a3ec01b4SVenkat Kumar Ande 	phy_data->mdio_addr = XP_GET_BITS(pdata->pp0, XP_PROP_0, MDIO_ADDR);
22944ac7516bSRavi Kumar 
2295a3ec01b4SVenkat Kumar Ande 	phy_data->redrv = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_PRESENT);
2296a3ec01b4SVenkat Kumar Ande 	phy_data->redrv_if = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_IF);
2297a3ec01b4SVenkat Kumar Ande 	phy_data->redrv_addr = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_ADDR);
2298a3ec01b4SVenkat Kumar Ande 	phy_data->redrv_lane = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_LANE);
2299a3ec01b4SVenkat Kumar Ande 	phy_data->redrv_model = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_MODEL);
23004ac7516bSRavi Kumar 
23014ac7516bSRavi Kumar 	/* Validate the connection requested */
23024ac7516bSRavi Kumar 	if (axgbe_phy_conn_type_mismatch(pdata)) {
2303*e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(ERR, "phy mode/connection mismatch (%#x/%#x)",
23044ac7516bSRavi Kumar 			    phy_data->port_mode, phy_data->conn_type);
23054ac7516bSRavi Kumar 		return -EINVAL;
23064ac7516bSRavi Kumar 	}
23074ac7516bSRavi Kumar 
23084ac7516bSRavi Kumar 	/* Validate the mode requested */
23094ac7516bSRavi Kumar 	if (axgbe_phy_port_mode_mismatch(pdata)) {
2310*e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(ERR, "phy mode/speed mismatch (%#x/%#x)",
23114ac7516bSRavi Kumar 			    phy_data->port_mode, phy_data->port_speeds);
23124ac7516bSRavi Kumar 		return -EINVAL;
23134ac7516bSRavi Kumar 	}
23144ac7516bSRavi Kumar 
23154ac7516bSRavi Kumar 	/* Check for and validate MDIO reset support */
23164ac7516bSRavi Kumar 	ret = axgbe_phy_mdio_reset_setup(pdata);
23174ac7516bSRavi Kumar 	if (ret)
23184ac7516bSRavi Kumar 		return ret;
23194ac7516bSRavi Kumar 
23204ac7516bSRavi Kumar 	/* Validate the re-driver information */
23214ac7516bSRavi Kumar 	if (axgbe_phy_redrv_error(phy_data)) {
2322*e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(ERR, "phy re-driver settings error");
23234ac7516bSRavi Kumar 		return -EINVAL;
23244ac7516bSRavi Kumar 	}
23254ac7516bSRavi Kumar 	pdata->kr_redrv = phy_data->redrv;
23264ac7516bSRavi Kumar 
23274ac7516bSRavi Kumar 	/* Indicate current mode is unknown */
23284ac7516bSRavi Kumar 	phy_data->cur_mode = AXGBE_MODE_UNKNOWN;
23294ac7516bSRavi Kumar 
23304ac7516bSRavi Kumar 	/* Initialize supported features */
23314ac7516bSRavi Kumar 	pdata->phy.supported = 0;
23324ac7516bSRavi Kumar 
23334ac7516bSRavi Kumar 	switch (phy_data->port_mode) {
23344ac7516bSRavi Kumar 		/* Backplane support */
23354ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE:
23364ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Autoneg;
2337443ab5aaSSelwin Sebastian 		/* Fallthrough */
2338443ab5aaSSelwin Sebastian 	case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG:
23394ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
23404ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Backplane;
23414ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) {
23424ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_1000baseKX_Full;
23434ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_KX_1000;
23444ac7516bSRavi Kumar 		}
23454ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) {
23464ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_10000baseKR_Full;
23474ac7516bSRavi Kumar 			if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
23484ac7516bSRavi Kumar 				pdata->phy.supported |=
23494ac7516bSRavi Kumar 					SUPPORTED_10000baseR_FEC;
23504ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_KR;
23514ac7516bSRavi Kumar 		}
23524ac7516bSRavi Kumar 
23534ac7516bSRavi Kumar 		phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE;
23544ac7516bSRavi Kumar 		break;
23554ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_BACKPLANE_2500:
23564ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
23574ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Backplane;
23584ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_2500baseX_Full;
23594ac7516bSRavi Kumar 		phy_data->start_mode = AXGBE_MODE_KX_2500;
23604ac7516bSRavi Kumar 
23614ac7516bSRavi Kumar 		phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE;
23624ac7516bSRavi Kumar 		break;
23634ac7516bSRavi Kumar 
23644ac7516bSRavi Kumar 		/* MDIO 1GBase-T support */
23654ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_T:
23664ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Autoneg;
23674ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
23684ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_TP;
23691f9d2d3aSVenkat Kumar Ande 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10) {
23701f9d2d3aSVenkat Kumar Ande 			pdata->phy.supported |= SUPPORTED_10baseT_Full;
23711f9d2d3aSVenkat Kumar Ande 			phy_data->start_mode = AXGBE_MODE_SGMII_10;
23721f9d2d3aSVenkat Kumar Ande 		}
23734ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) {
23744ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_100baseT_Full;
23754ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_SGMII_100;
23764ac7516bSRavi Kumar 		}
23774ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) {
23784ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_1000baseT_Full;
23794ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_SGMII_1000;
23804ac7516bSRavi Kumar 		}
23814ac7516bSRavi Kumar 
23824ac7516bSRavi Kumar 		phy_data->phydev_mode = AXGBE_MDIO_MODE_CL22;
23834ac7516bSRavi Kumar 		break;
23844ac7516bSRavi Kumar 
23854ac7516bSRavi Kumar 		/* MDIO Base-X support */
23864ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_1000BASE_X:
23874ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Autoneg;
23884ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
23894ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_FIBRE;
23904ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_1000baseT_Full;
23914ac7516bSRavi Kumar 		phy_data->start_mode = AXGBE_MODE_X;
23924ac7516bSRavi Kumar 
23934ac7516bSRavi Kumar 		phy_data->phydev_mode = AXGBE_MDIO_MODE_CL22;
23944ac7516bSRavi Kumar 		break;
23954ac7516bSRavi Kumar 
23964ac7516bSRavi Kumar 		/* MDIO NBase-T support */
23974ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_NBASE_T:
23984ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Autoneg;
23994ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
24004ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_TP;
24011f9d2d3aSVenkat Kumar Ande 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10) {
24021f9d2d3aSVenkat Kumar Ande 			pdata->phy.supported |= SUPPORTED_10baseT_Full;
24031f9d2d3aSVenkat Kumar Ande 			phy_data->start_mode = AXGBE_MODE_SGMII_10;
24041f9d2d3aSVenkat Kumar Ande 		}
24054ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) {
24064ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_100baseT_Full;
24074ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_SGMII_100;
24084ac7516bSRavi Kumar 		}
24094ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) {
24104ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_1000baseT_Full;
24114ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_SGMII_1000;
24124ac7516bSRavi Kumar 		}
24134ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500) {
24144ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_2500baseX_Full;
24154ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_KX_2500;
24164ac7516bSRavi Kumar 		}
24174ac7516bSRavi Kumar 
24184ac7516bSRavi Kumar 		phy_data->phydev_mode = AXGBE_MDIO_MODE_CL45;
24194ac7516bSRavi Kumar 		break;
24204ac7516bSRavi Kumar 
24214ac7516bSRavi Kumar 		/* 10GBase-T support */
24224ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_T:
24234ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Autoneg;
24244ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
24254ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_TP;
24261f9d2d3aSVenkat Kumar Ande 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10) {
24271f9d2d3aSVenkat Kumar Ande 			pdata->phy.supported |= SUPPORTED_10baseT_Full;
24281f9d2d3aSVenkat Kumar Ande 			phy_data->start_mode = AXGBE_MODE_SGMII_10;
24291f9d2d3aSVenkat Kumar Ande 		}
24304ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) {
24314ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_100baseT_Full;
24324ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_SGMII_100;
24334ac7516bSRavi Kumar 		}
24344ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) {
24354ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_1000baseT_Full;
24364ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_SGMII_1000;
24374ac7516bSRavi Kumar 		}
2438d7344a7bSVenkat Kumar Ande 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500) {
2439d7344a7bSVenkat Kumar Ande 			pdata->phy.supported |= SUPPORTED_2500baseX_Full;
2440d7344a7bSVenkat Kumar Ande 			phy_data->start_mode = AXGBE_MODE_KX_2500;
2441d7344a7bSVenkat Kumar Ande 		}
24424ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) {
24434ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_10000baseT_Full;
24444ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_KR;
24454ac7516bSRavi Kumar 		}
24464ac7516bSRavi Kumar 
24474ac7516bSRavi Kumar 		phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE;
24484ac7516bSRavi Kumar 		break;
24494ac7516bSRavi Kumar 
24504ac7516bSRavi Kumar 		/* 10GBase-R support */
24514ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_10GBASE_R:
24524ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Autoneg;
24534ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
24544ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_TP;
24554ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_10000baseT_Full;
24564ac7516bSRavi Kumar 		if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
24574ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_10000baseR_FEC;
24584ac7516bSRavi Kumar 		phy_data->start_mode = AXGBE_MODE_SFI;
24594ac7516bSRavi Kumar 
24604ac7516bSRavi Kumar 		phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE;
24614ac7516bSRavi Kumar 		break;
24624ac7516bSRavi Kumar 
24634ac7516bSRavi Kumar 		/* SFP support */
24644ac7516bSRavi Kumar 	case AXGBE_PORT_MODE_SFP:
24654ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Autoneg;
24664ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
24674ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_TP;
24684ac7516bSRavi Kumar 		pdata->phy.supported |= SUPPORTED_FIBRE;
24691f9d2d3aSVenkat Kumar Ande 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10) {
24701f9d2d3aSVenkat Kumar Ande 			pdata->phy.supported |= SUPPORTED_10baseT_Full;
24711f9d2d3aSVenkat Kumar Ande 			phy_data->start_mode = AXGBE_MODE_SGMII_10;
24721f9d2d3aSVenkat Kumar Ande 		}
24734ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) {
24744ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_100baseT_Full;
24754ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_SGMII_100;
24764ac7516bSRavi Kumar 		}
24774ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) {
24784ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_1000baseT_Full;
24794ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_SGMII_1000;
24804ac7516bSRavi Kumar 		}
24814ac7516bSRavi Kumar 		if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) {
24824ac7516bSRavi Kumar 			pdata->phy.supported |= SUPPORTED_10000baseT_Full;
24834ac7516bSRavi Kumar 			phy_data->start_mode = AXGBE_MODE_SFI;
24844ac7516bSRavi Kumar 			if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
24854ac7516bSRavi Kumar 				pdata->phy.supported |=
24864ac7516bSRavi Kumar 					SUPPORTED_10000baseR_FEC;
24874ac7516bSRavi Kumar 		}
24884ac7516bSRavi Kumar 
24894ac7516bSRavi Kumar 		phy_data->phydev_mode = AXGBE_MDIO_MODE_CL22;
24904ac7516bSRavi Kumar 
24914ac7516bSRavi Kumar 		axgbe_phy_sfp_setup(pdata);
24924ac7516bSRavi Kumar 		break;
24934ac7516bSRavi Kumar 	default:
24944ac7516bSRavi Kumar 		return -EINVAL;
24954ac7516bSRavi Kumar 	}
24964ac7516bSRavi Kumar 
24974ac7516bSRavi Kumar 	if ((phy_data->conn_type & AXGBE_CONN_TYPE_MDIO) &&
24984ac7516bSRavi Kumar 	    (phy_data->phydev_mode != AXGBE_MDIO_MODE_NONE)) {
24994ac7516bSRavi Kumar 		ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->mdio_addr,
25004ac7516bSRavi Kumar 						    phy_data->phydev_mode);
25014ac7516bSRavi Kumar 		if (ret) {
2502*e99981afSDavid Marchand 			PMD_DRV_LOG_LINE(ERR, "mdio port/clause not compatible (%d/%u)",
25034ac7516bSRavi Kumar 				    phy_data->mdio_addr, phy_data->phydev_mode);
25044ac7516bSRavi Kumar 			return -EINVAL;
25054ac7516bSRavi Kumar 		}
25064ac7516bSRavi Kumar 	}
25074ac7516bSRavi Kumar 
25084ac7516bSRavi Kumar 	if (phy_data->redrv && !phy_data->redrv_if) {
25094ac7516bSRavi Kumar 		ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->redrv_addr,
25104ac7516bSRavi Kumar 						    AXGBE_MDIO_MODE_CL22);
25114ac7516bSRavi Kumar 		if (ret) {
2512*e99981afSDavid Marchand 			PMD_DRV_LOG_LINE(ERR, "redriver mdio port not compatible (%u)",
25134ac7516bSRavi Kumar 				    phy_data->redrv_addr);
25144ac7516bSRavi Kumar 			return -EINVAL;
25154ac7516bSRavi Kumar 		}
25164ac7516bSRavi Kumar 	}
251700072056SRavi Kumar 
251800072056SRavi Kumar 	phy_data->phy_cdr_delay = AXGBE_CDR_DELAY_INIT;
25194ac7516bSRavi Kumar 	return 0;
25204ac7516bSRavi Kumar }
25214ac7516bSRavi Kumar void axgbe_init_function_ptrs_phy_v2(struct axgbe_phy_if *phy_if)
25224ac7516bSRavi Kumar {
25234ac7516bSRavi Kumar 	struct axgbe_phy_impl_if *phy_impl = &phy_if->phy_impl;
25244ac7516bSRavi Kumar 
25254ac7516bSRavi Kumar 	phy_impl->init			= axgbe_phy_init;
2526a5c72737SRavi Kumar 	phy_impl->reset			= axgbe_phy_reset;
2527a5c72737SRavi Kumar 	phy_impl->start			= axgbe_phy_start;
2528a5c72737SRavi Kumar 	phy_impl->stop			= axgbe_phy_stop;
2529a5c72737SRavi Kumar 	phy_impl->link_status		= axgbe_phy_link_status;
2530a5c72737SRavi Kumar 	phy_impl->use_mode		= axgbe_phy_use_mode;
2531a5c72737SRavi Kumar 	phy_impl->set_mode		= axgbe_phy_set_mode;
2532a5c72737SRavi Kumar 	phy_impl->get_mode		= axgbe_phy_get_mode;
2533a5c72737SRavi Kumar 	phy_impl->switch_mode		= axgbe_phy_switch_mode;
2534a5c72737SRavi Kumar 	phy_impl->cur_mode		= axgbe_phy_cur_mode;
2535a5c72737SRavi Kumar 	phy_impl->an_mode		= axgbe_phy_an_mode;
2536a5c72737SRavi Kumar 	phy_impl->an_config		= axgbe_phy_an_config;
2537a5c72737SRavi Kumar 	phy_impl->an_advertising	= axgbe_phy_an_advertising;
2538a5c72737SRavi Kumar 	phy_impl->an_outcome		= axgbe_phy_an_outcome;
253900072056SRavi Kumar 
254000072056SRavi Kumar 	phy_impl->an_pre		= axgbe_phy_an_pre;
254100072056SRavi Kumar 	phy_impl->an_post		= axgbe_phy_an_post;
254200072056SRavi Kumar 
254300072056SRavi Kumar 	phy_impl->kr_training_pre	= axgbe_phy_kr_training_pre;
254400072056SRavi Kumar 	phy_impl->kr_training_post	= axgbe_phy_kr_training_post;
25454ac7516bSRavi Kumar }
2546