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