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 10*1f9d2d3aSVenkat Kumar Ande #define AXGBE_PHY_PORT_SPEED_10 BIT(0) 11a935a4c3SSelwin Sebastian #define AXGBE_PHY_PORT_SPEED_100 BIT(1) 12a935a4c3SSelwin Sebastian #define AXGBE_PHY_PORT_SPEED_1000 BIT(2) 13a935a4c3SSelwin Sebastian #define AXGBE_PHY_PORT_SPEED_2500 BIT(3) 14a935a4c3SSelwin Sebastian #define AXGBE_PHY_PORT_SPEED_10000 BIT(4) 154ac7516bSRavi Kumar 164ac7516bSRavi Kumar #define AXGBE_MUTEX_RELEASE 0x80000000 174ac7516bSRavi Kumar 184ac7516bSRavi Kumar #define AXGBE_SFP_DIRECT 7 194ac7516bSRavi Kumar 204ac7516bSRavi Kumar /* I2C target addresses */ 214ac7516bSRavi Kumar #define AXGBE_SFP_SERIAL_ID_ADDRESS 0x50 224ac7516bSRavi Kumar #define AXGBE_SFP_DIAG_INFO_ADDRESS 0x51 234ac7516bSRavi Kumar #define AXGBE_SFP_PHY_ADDRESS 0x56 244ac7516bSRavi Kumar #define AXGBE_GPIO_ADDRESS_PCA9555 0x20 254ac7516bSRavi Kumar 264ac7516bSRavi Kumar /* SFP sideband signal indicators */ 274ac7516bSRavi Kumar #define AXGBE_GPIO_NO_TX_FAULT BIT(0) 284ac7516bSRavi Kumar #define AXGBE_GPIO_NO_RATE_SELECT BIT(1) 294ac7516bSRavi Kumar #define AXGBE_GPIO_NO_MOD_ABSENT BIT(2) 304ac7516bSRavi Kumar #define AXGBE_GPIO_NO_RX_LOS BIT(3) 314ac7516bSRavi Kumar 324ac7516bSRavi Kumar /* Rate-change complete wait/retry count */ 334ac7516bSRavi Kumar #define AXGBE_RATECHANGE_COUNT 500 344ac7516bSRavi Kumar 3500072056SRavi Kumar /* CDR delay values for KR support (in usec) */ 3600072056SRavi Kumar #define AXGBE_CDR_DELAY_INIT 10000 3700072056SRavi Kumar #define AXGBE_CDR_DELAY_INC 10000 3800072056SRavi Kumar #define AXGBE_CDR_DELAY_MAX 100000 3900072056SRavi Kumar 404ac7516bSRavi Kumar enum axgbe_port_mode { 414ac7516bSRavi Kumar AXGBE_PORT_MODE_RSVD = 0, 424ac7516bSRavi Kumar AXGBE_PORT_MODE_BACKPLANE, 434ac7516bSRavi Kumar AXGBE_PORT_MODE_BACKPLANE_2500, 444ac7516bSRavi Kumar AXGBE_PORT_MODE_1000BASE_T, 454ac7516bSRavi Kumar AXGBE_PORT_MODE_1000BASE_X, 464ac7516bSRavi Kumar AXGBE_PORT_MODE_NBASE_T, 474ac7516bSRavi Kumar AXGBE_PORT_MODE_10GBASE_T, 484ac7516bSRavi Kumar AXGBE_PORT_MODE_10GBASE_R, 494ac7516bSRavi Kumar AXGBE_PORT_MODE_SFP, 50443ab5aaSSelwin Sebastian AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG, 514ac7516bSRavi Kumar AXGBE_PORT_MODE_MAX, 524ac7516bSRavi Kumar }; 534ac7516bSRavi Kumar 544ac7516bSRavi Kumar enum axgbe_conn_type { 554ac7516bSRavi Kumar AXGBE_CONN_TYPE_NONE = 0, 564ac7516bSRavi Kumar AXGBE_CONN_TYPE_SFP, 574ac7516bSRavi Kumar AXGBE_CONN_TYPE_MDIO, 584ac7516bSRavi Kumar AXGBE_CONN_TYPE_RSVD1, 594ac7516bSRavi Kumar AXGBE_CONN_TYPE_BACKPLANE, 604ac7516bSRavi Kumar AXGBE_CONN_TYPE_MAX, 614ac7516bSRavi Kumar }; 624ac7516bSRavi Kumar 634ac7516bSRavi Kumar /* SFP/SFP+ related definitions */ 644ac7516bSRavi Kumar enum axgbe_sfp_comm { 654ac7516bSRavi Kumar AXGBE_SFP_COMM_DIRECT = 0, 664ac7516bSRavi Kumar AXGBE_SFP_COMM_PCA9545, 674ac7516bSRavi Kumar }; 684ac7516bSRavi Kumar 694ac7516bSRavi Kumar enum axgbe_sfp_cable { 704ac7516bSRavi Kumar AXGBE_SFP_CABLE_UNKNOWN = 0, 714ac7516bSRavi Kumar AXGBE_SFP_CABLE_ACTIVE, 724ac7516bSRavi Kumar AXGBE_SFP_CABLE_PASSIVE, 734823ccdbSVenkat Kumar Ande AXGBE_SFP_CABLE_FIBER, 744ac7516bSRavi Kumar }; 754ac7516bSRavi Kumar 764ac7516bSRavi Kumar enum axgbe_sfp_base { 774ac7516bSRavi Kumar AXGBE_SFP_BASE_UNKNOWN = 0, 784ac7516bSRavi Kumar AXGBE_SFP_BASE_1000_T, 794ac7516bSRavi Kumar AXGBE_SFP_BASE_1000_SX, 804ac7516bSRavi Kumar AXGBE_SFP_BASE_1000_LX, 814ac7516bSRavi Kumar AXGBE_SFP_BASE_1000_CX, 824ac7516bSRavi Kumar AXGBE_SFP_BASE_10000_SR, 834ac7516bSRavi Kumar AXGBE_SFP_BASE_10000_LR, 844ac7516bSRavi Kumar AXGBE_SFP_BASE_10000_LRM, 854ac7516bSRavi Kumar AXGBE_SFP_BASE_10000_ER, 864ac7516bSRavi Kumar AXGBE_SFP_BASE_10000_CR, 874ac7516bSRavi Kumar }; 884ac7516bSRavi Kumar 894ac7516bSRavi Kumar enum axgbe_sfp_speed { 904ac7516bSRavi Kumar AXGBE_SFP_SPEED_UNKNOWN = 0, 914ac7516bSRavi Kumar AXGBE_SFP_SPEED_100_1000, 924ac7516bSRavi Kumar AXGBE_SFP_SPEED_1000, 934ac7516bSRavi Kumar AXGBE_SFP_SPEED_10000, 944ac7516bSRavi Kumar }; 954ac7516bSRavi Kumar 964ac7516bSRavi Kumar /* SFP Serial ID Base ID values relative to an offset of 0 */ 974ac7516bSRavi Kumar #define AXGBE_SFP_BASE_ID 0 984ac7516bSRavi Kumar #define AXGBE_SFP_ID_SFP 0x03 994ac7516bSRavi Kumar 1004ac7516bSRavi Kumar #define AXGBE_SFP_BASE_EXT_ID 1 1014ac7516bSRavi Kumar #define AXGBE_SFP_EXT_ID_SFP 0x04 1024ac7516bSRavi Kumar 1034ac7516bSRavi Kumar #define AXGBE_SFP_BASE_10GBE_CC 3 1044ac7516bSRavi Kumar #define AXGBE_SFP_BASE_10GBE_CC_SR BIT(4) 1054ac7516bSRavi Kumar #define AXGBE_SFP_BASE_10GBE_CC_LR BIT(5) 1064ac7516bSRavi Kumar #define AXGBE_SFP_BASE_10GBE_CC_LRM BIT(6) 1074ac7516bSRavi Kumar #define AXGBE_SFP_BASE_10GBE_CC_ER BIT(7) 1084ac7516bSRavi Kumar 1094ac7516bSRavi Kumar #define AXGBE_SFP_BASE_1GBE_CC 6 1104ac7516bSRavi Kumar #define AXGBE_SFP_BASE_1GBE_CC_SX BIT(0) 1114ac7516bSRavi Kumar #define AXGBE_SFP_BASE_1GBE_CC_LX BIT(1) 1124ac7516bSRavi Kumar #define AXGBE_SFP_BASE_1GBE_CC_CX BIT(2) 1134ac7516bSRavi Kumar #define AXGBE_SFP_BASE_1GBE_CC_T BIT(3) 1144ac7516bSRavi Kumar 1154ac7516bSRavi Kumar #define AXGBE_SFP_BASE_CABLE 8 1164ac7516bSRavi Kumar #define AXGBE_SFP_BASE_CABLE_PASSIVE BIT(2) 1174ac7516bSRavi Kumar #define AXGBE_SFP_BASE_CABLE_ACTIVE BIT(3) 1184ac7516bSRavi Kumar 1194ac7516bSRavi Kumar #define AXGBE_SFP_BASE_BR 12 1204ac7516bSRavi Kumar #define AXGBE_SFP_BASE_BR_1GBE_MIN 0x0a 1214ac7516bSRavi Kumar #define AXGBE_SFP_BASE_BR_10GBE_MIN 0x64 1224ac7516bSRavi Kumar 1234ac7516bSRavi Kumar #define AXGBE_SFP_BASE_CU_CABLE_LEN 18 1244ac7516bSRavi Kumar 1254ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_NAME 20 1264ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_NAME_LEN 16 1274ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_PN 40 1284ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_PN_LEN 16 1294ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_REV 56 1304ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_REV_LEN 4 1314ac7516bSRavi Kumar 1324ac7516bSRavi Kumar #define AXGBE_SFP_BASE_CC 63 1334ac7516bSRavi Kumar 1344ac7516bSRavi Kumar /* SFP Serial ID Extended ID values relative to an offset of 64 */ 1354ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_SN 4 1364ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_SN_LEN 16 1374ac7516bSRavi Kumar 1384ac7516bSRavi Kumar #define AXGBE_SFP_EXTD_DIAG 28 1394ac7516bSRavi Kumar #define AXGBE_SFP_EXTD_DIAG_ADDR_CHANGE BIT(2) 1404ac7516bSRavi Kumar 1414ac7516bSRavi Kumar #define AXGBE_SFP_EXTD_SFF_8472 30 1424ac7516bSRavi Kumar 1434ac7516bSRavi Kumar #define AXGBE_SFP_EXTD_CC 31 1444ac7516bSRavi Kumar 1454ac7516bSRavi Kumar struct axgbe_sfp_eeprom { 1464ac7516bSRavi Kumar u8 base[64]; 1474ac7516bSRavi Kumar u8 extd[32]; 1484ac7516bSRavi Kumar u8 vendor[32]; 1494ac7516bSRavi Kumar }; 1504ac7516bSRavi Kumar 1514ac7516bSRavi Kumar #define AXGBE_BEL_FUSE_VENDOR "BEL-FUSE" 1524ac7516bSRavi Kumar #define AXGBE_BEL_FUSE_PARTNO "1GBT-SFP06" 1534ac7516bSRavi Kumar 1544ac7516bSRavi Kumar struct axgbe_sfp_ascii { 1554ac7516bSRavi Kumar union { 1564ac7516bSRavi Kumar char vendor[AXGBE_SFP_BASE_VENDOR_NAME_LEN + 1]; 1574ac7516bSRavi Kumar char partno[AXGBE_SFP_BASE_VENDOR_PN_LEN + 1]; 1584ac7516bSRavi Kumar char rev[AXGBE_SFP_BASE_VENDOR_REV_LEN + 1]; 1594ac7516bSRavi Kumar char serno[AXGBE_SFP_BASE_VENDOR_SN_LEN + 1]; 1604ac7516bSRavi Kumar } u; 1614ac7516bSRavi Kumar }; 1624ac7516bSRavi Kumar 1634ac7516bSRavi Kumar /* MDIO PHY reset types */ 1644ac7516bSRavi Kumar enum axgbe_mdio_reset { 1654ac7516bSRavi Kumar AXGBE_MDIO_RESET_NONE = 0, 1664ac7516bSRavi Kumar AXGBE_MDIO_RESET_I2C_GPIO, 1674ac7516bSRavi Kumar AXGBE_MDIO_RESET_INT_GPIO, 1684ac7516bSRavi Kumar AXGBE_MDIO_RESET_MAX, 1694ac7516bSRavi Kumar }; 1704ac7516bSRavi Kumar 1714ac7516bSRavi Kumar /* Re-driver related definitions */ 1724ac7516bSRavi Kumar enum axgbe_phy_redrv_if { 1734ac7516bSRavi Kumar AXGBE_PHY_REDRV_IF_MDIO = 0, 1744ac7516bSRavi Kumar AXGBE_PHY_REDRV_IF_I2C, 1754ac7516bSRavi Kumar AXGBE_PHY_REDRV_IF_MAX, 1764ac7516bSRavi Kumar }; 1774ac7516bSRavi Kumar 1784ac7516bSRavi Kumar enum axgbe_phy_redrv_model { 1794ac7516bSRavi Kumar AXGBE_PHY_REDRV_MODEL_4223 = 0, 1804ac7516bSRavi Kumar AXGBE_PHY_REDRV_MODEL_4227, 1814ac7516bSRavi Kumar AXGBE_PHY_REDRV_MODEL_MAX, 1824ac7516bSRavi Kumar }; 1834ac7516bSRavi Kumar 1844ac7516bSRavi Kumar enum axgbe_phy_redrv_mode { 1854ac7516bSRavi Kumar AXGBE_PHY_REDRV_MODE_CX = 5, 1864ac7516bSRavi Kumar AXGBE_PHY_REDRV_MODE_SR = 9, 1874ac7516bSRavi Kumar }; 1884ac7516bSRavi Kumar 1894ac7516bSRavi Kumar #define AXGBE_PHY_REDRV_MODE_REG 0x12b0 1904ac7516bSRavi Kumar 1914ac7516bSRavi Kumar /* PHY related configuration information */ 1924ac7516bSRavi Kumar struct axgbe_phy_data { 1934ac7516bSRavi Kumar enum axgbe_port_mode port_mode; 1944ac7516bSRavi Kumar 1954ac7516bSRavi Kumar unsigned int port_id; 1964ac7516bSRavi Kumar 1974ac7516bSRavi Kumar unsigned int port_speeds; 1984ac7516bSRavi Kumar 1994ac7516bSRavi Kumar enum axgbe_conn_type conn_type; 2004ac7516bSRavi Kumar 2014ac7516bSRavi Kumar enum axgbe_mode cur_mode; 2024ac7516bSRavi Kumar enum axgbe_mode start_mode; 2034ac7516bSRavi Kumar 2044ac7516bSRavi Kumar unsigned int rrc_count; 2054ac7516bSRavi Kumar 2064ac7516bSRavi Kumar unsigned int mdio_addr; 2074ac7516bSRavi Kumar 2084ac7516bSRavi Kumar /* SFP Support */ 2094ac7516bSRavi Kumar enum axgbe_sfp_comm sfp_comm; 2104ac7516bSRavi Kumar unsigned int sfp_mux_address; 2114ac7516bSRavi Kumar unsigned int sfp_mux_channel; 2124ac7516bSRavi Kumar 2134ac7516bSRavi Kumar unsigned int sfp_gpio_address; 2144ac7516bSRavi Kumar unsigned int sfp_gpio_mask; 2154ac7516bSRavi Kumar unsigned int sfp_gpio_rx_los; 2164ac7516bSRavi Kumar unsigned int sfp_gpio_tx_fault; 2174ac7516bSRavi Kumar unsigned int sfp_gpio_mod_absent; 2184ac7516bSRavi Kumar unsigned int sfp_gpio_rate_select; 2194ac7516bSRavi Kumar 2204ac7516bSRavi Kumar unsigned int sfp_rx_los; 2214ac7516bSRavi Kumar unsigned int sfp_tx_fault; 2224ac7516bSRavi Kumar unsigned int sfp_mod_absent; 2234ac7516bSRavi Kumar unsigned int sfp_changed; 2244ac7516bSRavi Kumar unsigned int sfp_phy_avail; 2254ac7516bSRavi Kumar unsigned int sfp_cable_len; 2264ac7516bSRavi Kumar enum axgbe_sfp_base sfp_base; 2274ac7516bSRavi Kumar enum axgbe_sfp_cable sfp_cable; 2284ac7516bSRavi Kumar enum axgbe_sfp_speed sfp_speed; 2294ac7516bSRavi Kumar struct axgbe_sfp_eeprom sfp_eeprom; 2304ac7516bSRavi Kumar 2314ac7516bSRavi Kumar /* External PHY support */ 2324ac7516bSRavi Kumar enum axgbe_mdio_mode phydev_mode; 2334ac7516bSRavi Kumar enum axgbe_mdio_reset mdio_reset; 2344ac7516bSRavi Kumar unsigned int mdio_reset_addr; 2354ac7516bSRavi Kumar unsigned int mdio_reset_gpio; 2364ac7516bSRavi Kumar 2374ac7516bSRavi Kumar /* Re-driver support */ 2384ac7516bSRavi Kumar unsigned int redrv; 2394ac7516bSRavi Kumar unsigned int redrv_if; 2404ac7516bSRavi Kumar unsigned int redrv_addr; 2414ac7516bSRavi Kumar unsigned int redrv_lane; 2424ac7516bSRavi Kumar unsigned int redrv_model; 24300072056SRavi Kumar 24400072056SRavi Kumar /* KR AN support */ 24500072056SRavi Kumar unsigned int phy_cdr_notrack; 24600072056SRavi Kumar unsigned int phy_cdr_delay; 2474ac7516bSRavi Kumar }; 2484ac7516bSRavi Kumar 249a5c72737SRavi Kumar static enum axgbe_an_mode axgbe_phy_an_mode(struct axgbe_port *pdata); 250a5c72737SRavi Kumar 251a5c72737SRavi Kumar static int axgbe_phy_i2c_xfer(struct axgbe_port *pdata, 252a5c72737SRavi Kumar struct axgbe_i2c_op *i2c_op) 253a5c72737SRavi Kumar { 254a5c72737SRavi Kumar return pdata->i2c_if.i2c_xfer(pdata, i2c_op); 255a5c72737SRavi Kumar } 256a5c72737SRavi Kumar 257a5c72737SRavi Kumar static int axgbe_phy_redrv_write(struct axgbe_port *pdata, unsigned int reg, 258a5c72737SRavi Kumar unsigned int val) 259a5c72737SRavi Kumar { 260a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 261a5c72737SRavi Kumar struct axgbe_i2c_op i2c_op; 262a5c72737SRavi Kumar uint16_t *redrv_val; 263a5c72737SRavi Kumar u8 redrv_data[5], csum; 264a5c72737SRavi Kumar unsigned int i, retry; 265a5c72737SRavi Kumar int ret; 266a5c72737SRavi Kumar 267a5c72737SRavi Kumar /* High byte of register contains read/write indicator */ 268a5c72737SRavi Kumar redrv_data[0] = ((reg >> 8) & 0xff) << 1; 269a5c72737SRavi Kumar redrv_data[1] = reg & 0xff; 270a5c72737SRavi Kumar redrv_val = (uint16_t *)&redrv_data[2]; 271a5c72737SRavi Kumar *redrv_val = rte_cpu_to_be_16(val); 272a5c72737SRavi Kumar 273a5c72737SRavi Kumar /* Calculate 1 byte checksum */ 274a5c72737SRavi Kumar csum = 0; 275a5c72737SRavi Kumar for (i = 0; i < 4; i++) { 276a5c72737SRavi Kumar csum += redrv_data[i]; 277a5c72737SRavi Kumar if (redrv_data[i] > csum) 278a5c72737SRavi Kumar csum++; 279a5c72737SRavi Kumar } 280a5c72737SRavi Kumar redrv_data[4] = ~csum; 281a5c72737SRavi Kumar 282a5c72737SRavi Kumar retry = 1; 283a5c72737SRavi Kumar again1: 284a5c72737SRavi Kumar i2c_op.cmd = AXGBE_I2C_CMD_WRITE; 285a5c72737SRavi Kumar i2c_op.target = phy_data->redrv_addr; 286a5c72737SRavi Kumar i2c_op.len = sizeof(redrv_data); 287a5c72737SRavi Kumar i2c_op.buf = redrv_data; 288a5c72737SRavi Kumar ret = axgbe_phy_i2c_xfer(pdata, &i2c_op); 289a5c72737SRavi Kumar if (ret) { 290a5c72737SRavi Kumar if ((ret == -EAGAIN) && retry--) 291a5c72737SRavi Kumar goto again1; 292a5c72737SRavi Kumar 293a5c72737SRavi Kumar return ret; 294a5c72737SRavi Kumar } 295a5c72737SRavi Kumar 296a5c72737SRavi Kumar retry = 1; 297a5c72737SRavi Kumar again2: 298a5c72737SRavi Kumar i2c_op.cmd = AXGBE_I2C_CMD_READ; 299a5c72737SRavi Kumar i2c_op.target = phy_data->redrv_addr; 300a5c72737SRavi Kumar i2c_op.len = 1; 301a5c72737SRavi Kumar i2c_op.buf = redrv_data; 302a5c72737SRavi Kumar ret = axgbe_phy_i2c_xfer(pdata, &i2c_op); 303a5c72737SRavi Kumar if (ret) { 304a5c72737SRavi Kumar if ((ret == -EAGAIN) && retry--) 305a5c72737SRavi Kumar goto again2; 306a5c72737SRavi Kumar 307a5c72737SRavi Kumar return ret; 308a5c72737SRavi Kumar } 309a5c72737SRavi Kumar 310a5c72737SRavi Kumar if (redrv_data[0] != 0xff) { 311a5c72737SRavi Kumar PMD_DRV_LOG(ERR, "Redriver write checksum error\n"); 312a5c72737SRavi Kumar ret = -EIO; 313a5c72737SRavi Kumar } 314a5c72737SRavi Kumar 315a5c72737SRavi Kumar return ret; 316a5c72737SRavi Kumar } 317a5c72737SRavi Kumar 318a5c72737SRavi Kumar static int axgbe_phy_i2c_read(struct axgbe_port *pdata, unsigned int target, 319a5c72737SRavi Kumar void *reg, unsigned int reg_len, 320a5c72737SRavi Kumar void *val, unsigned int val_len) 321a5c72737SRavi Kumar { 322a5c72737SRavi Kumar struct axgbe_i2c_op i2c_op; 323a5c72737SRavi Kumar int retry, ret; 324a5c72737SRavi Kumar 325a5c72737SRavi Kumar retry = 1; 326a5c72737SRavi Kumar again1: 327a5c72737SRavi Kumar /* Set the specified register to read */ 328a5c72737SRavi Kumar i2c_op.cmd = AXGBE_I2C_CMD_WRITE; 329a5c72737SRavi Kumar i2c_op.target = target; 330a5c72737SRavi Kumar i2c_op.len = reg_len; 331a5c72737SRavi Kumar i2c_op.buf = reg; 332a5c72737SRavi Kumar ret = axgbe_phy_i2c_xfer(pdata, &i2c_op); 333a5c72737SRavi Kumar if (ret) { 334a5c72737SRavi Kumar if ((ret == -EAGAIN) && retry--) 335a5c72737SRavi Kumar goto again1; 336a5c72737SRavi Kumar 337a5c72737SRavi Kumar return ret; 338a5c72737SRavi Kumar } 339a5c72737SRavi Kumar 340a5c72737SRavi Kumar retry = 1; 341a5c72737SRavi Kumar again2: 3427be78d02SJosh Soref /* Read the specified register */ 343a5c72737SRavi Kumar i2c_op.cmd = AXGBE_I2C_CMD_READ; 344a5c72737SRavi Kumar i2c_op.target = target; 345a5c72737SRavi Kumar i2c_op.len = val_len; 346a5c72737SRavi Kumar i2c_op.buf = val; 347a5c72737SRavi Kumar ret = axgbe_phy_i2c_xfer(pdata, &i2c_op); 348a5c72737SRavi Kumar if ((ret == -EAGAIN) && retry--) 349a5c72737SRavi Kumar goto again2; 350a5c72737SRavi Kumar 351a5c72737SRavi Kumar return ret; 352a5c72737SRavi Kumar } 353a5c72737SRavi Kumar 354a5c72737SRavi Kumar static int axgbe_phy_sfp_put_mux(struct axgbe_port *pdata) 355a5c72737SRavi Kumar { 356a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 357a5c72737SRavi Kumar struct axgbe_i2c_op i2c_op; 358a5c72737SRavi Kumar uint8_t mux_channel; 359a5c72737SRavi Kumar 360a5c72737SRavi Kumar if (phy_data->sfp_comm == AXGBE_SFP_COMM_DIRECT) 361a5c72737SRavi Kumar return 0; 362a5c72737SRavi Kumar 363a5c72737SRavi Kumar /* Select no mux channels */ 364a5c72737SRavi Kumar mux_channel = 0; 365a5c72737SRavi Kumar i2c_op.cmd = AXGBE_I2C_CMD_WRITE; 366a5c72737SRavi Kumar i2c_op.target = phy_data->sfp_mux_address; 367a5c72737SRavi Kumar i2c_op.len = sizeof(mux_channel); 368a5c72737SRavi Kumar i2c_op.buf = &mux_channel; 369a5c72737SRavi Kumar 370a5c72737SRavi Kumar return axgbe_phy_i2c_xfer(pdata, &i2c_op); 371a5c72737SRavi Kumar } 372a5c72737SRavi Kumar 373a5c72737SRavi Kumar static int axgbe_phy_sfp_get_mux(struct axgbe_port *pdata) 374a5c72737SRavi Kumar { 375a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 376a5c72737SRavi Kumar struct axgbe_i2c_op i2c_op; 377a5c72737SRavi Kumar u8 mux_channel; 378a5c72737SRavi Kumar 379a5c72737SRavi Kumar if (phy_data->sfp_comm == AXGBE_SFP_COMM_DIRECT) 380a5c72737SRavi Kumar return 0; 381a5c72737SRavi Kumar 382a5c72737SRavi Kumar /* Select desired mux channel */ 383a5c72737SRavi Kumar mux_channel = 1 << phy_data->sfp_mux_channel; 384a5c72737SRavi Kumar i2c_op.cmd = AXGBE_I2C_CMD_WRITE; 385a5c72737SRavi Kumar i2c_op.target = phy_data->sfp_mux_address; 386a5c72737SRavi Kumar i2c_op.len = sizeof(mux_channel); 387a5c72737SRavi Kumar i2c_op.buf = &mux_channel; 388a5c72737SRavi Kumar 389a5c72737SRavi Kumar return axgbe_phy_i2c_xfer(pdata, &i2c_op); 390a5c72737SRavi Kumar } 391a5c72737SRavi Kumar 392a5c72737SRavi Kumar static void axgbe_phy_put_comm_ownership(struct axgbe_port *pdata) 393a5c72737SRavi Kumar { 394a5c72737SRavi Kumar pthread_mutex_unlock(&pdata->phy_mutex); 395a5c72737SRavi Kumar } 396a5c72737SRavi Kumar 397a5c72737SRavi Kumar static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata) 398a5c72737SRavi Kumar { 399a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 400a5c72737SRavi Kumar uint64_t timeout; 401a5c72737SRavi Kumar unsigned int mutex_id; 402a5c72737SRavi Kumar 403a5c72737SRavi Kumar /* The I2C and MDIO/GPIO bus is multiplexed between multiple devices, 404a5c72737SRavi Kumar * the driver needs to take the software mutex and then the hardware 405a5c72737SRavi Kumar * mutexes before being able to use the busses. 406a5c72737SRavi Kumar */ 407a5c72737SRavi Kumar pthread_mutex_lock(&pdata->phy_mutex); 408a5c72737SRavi Kumar 409a5c72737SRavi Kumar /* Clear the mutexes */ 410a5c72737SRavi Kumar XP_IOWRITE(pdata, XP_I2C_MUTEX, AXGBE_MUTEX_RELEASE); 411a5c72737SRavi Kumar XP_IOWRITE(pdata, XP_MDIO_MUTEX, AXGBE_MUTEX_RELEASE); 412a5c72737SRavi Kumar 413a5c72737SRavi Kumar /* Mutex formats are the same for I2C and MDIO/GPIO */ 414a5c72737SRavi Kumar mutex_id = 0; 415a5c72737SRavi Kumar XP_SET_BITS(mutex_id, XP_I2C_MUTEX, ID, phy_data->port_id); 416a5c72737SRavi Kumar XP_SET_BITS(mutex_id, XP_I2C_MUTEX, ACTIVE, 1); 417a5c72737SRavi Kumar 418a5c72737SRavi Kumar timeout = rte_get_timer_cycles() + (rte_get_timer_hz() * 5); 419a5c72737SRavi Kumar while (time_before(rte_get_timer_cycles(), timeout)) { 420a5c72737SRavi Kumar /* Must be all zeroes in order to obtain the mutex */ 421a5c72737SRavi Kumar if (XP_IOREAD(pdata, XP_I2C_MUTEX) || 422a5c72737SRavi Kumar XP_IOREAD(pdata, XP_MDIO_MUTEX)) { 423a5c72737SRavi Kumar rte_delay_us(100); 424a5c72737SRavi Kumar continue; 425a5c72737SRavi Kumar } 426a5c72737SRavi Kumar 427a5c72737SRavi Kumar /* Obtain the mutex */ 428a5c72737SRavi Kumar XP_IOWRITE(pdata, XP_I2C_MUTEX, mutex_id); 429a5c72737SRavi Kumar XP_IOWRITE(pdata, XP_MDIO_MUTEX, mutex_id); 430a5c72737SRavi Kumar 431a5c72737SRavi Kumar return 0; 432a5c72737SRavi Kumar } 433a5c72737SRavi Kumar 434a5c72737SRavi Kumar pthread_mutex_unlock(&pdata->phy_mutex); 435a5c72737SRavi Kumar 436a5c72737SRavi Kumar PMD_DRV_LOG(ERR, "unable to obtain hardware mutexes\n"); 437a5c72737SRavi Kumar 438a5c72737SRavi Kumar return -ETIMEDOUT; 439a5c72737SRavi Kumar } 440a5c72737SRavi Kumar 441a5c72737SRavi Kumar static void axgbe_phy_sfp_phy_settings(struct axgbe_port *pdata) 442a5c72737SRavi Kumar { 443a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 444a5c72737SRavi Kumar 445a5c72737SRavi Kumar if (phy_data->sfp_mod_absent) { 446a5c72737SRavi Kumar pdata->phy.speed = SPEED_UNKNOWN; 447a5c72737SRavi Kumar pdata->phy.duplex = DUPLEX_UNKNOWN; 448a5c72737SRavi Kumar pdata->phy.autoneg = AUTONEG_ENABLE; 449a5c72737SRavi Kumar pdata->phy.advertising = pdata->phy.supported; 450a5c72737SRavi Kumar } 451a5c72737SRavi Kumar 452a5c72737SRavi Kumar pdata->phy.advertising &= ~ADVERTISED_Autoneg; 453a5c72737SRavi Kumar pdata->phy.advertising &= ~ADVERTISED_TP; 454a5c72737SRavi Kumar pdata->phy.advertising &= ~ADVERTISED_FIBRE; 455a5c72737SRavi Kumar pdata->phy.advertising &= ~ADVERTISED_100baseT_Full; 456a5c72737SRavi Kumar pdata->phy.advertising &= ~ADVERTISED_1000baseT_Full; 457a5c72737SRavi Kumar pdata->phy.advertising &= ~ADVERTISED_10000baseT_Full; 458a5c72737SRavi Kumar pdata->phy.advertising &= ~ADVERTISED_10000baseR_FEC; 459a5c72737SRavi Kumar 460a5c72737SRavi Kumar switch (phy_data->sfp_base) { 461a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_T: 462a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_SX: 463a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_LX: 464a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_CX: 465a5c72737SRavi Kumar pdata->phy.speed = SPEED_UNKNOWN; 466a5c72737SRavi Kumar pdata->phy.duplex = DUPLEX_UNKNOWN; 467a5c72737SRavi Kumar pdata->phy.autoneg = AUTONEG_ENABLE; 468a5c72737SRavi Kumar pdata->phy.advertising |= ADVERTISED_Autoneg; 469a5c72737SRavi Kumar break; 470a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_SR: 471a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_LR: 472a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_LRM: 473a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_ER: 474a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_CR: 475a5c72737SRavi Kumar default: 476a5c72737SRavi Kumar pdata->phy.speed = SPEED_10000; 477a5c72737SRavi Kumar pdata->phy.duplex = DUPLEX_FULL; 478a5c72737SRavi Kumar pdata->phy.autoneg = AUTONEG_DISABLE; 479a5c72737SRavi Kumar break; 480a5c72737SRavi Kumar } 481a5c72737SRavi Kumar 482a5c72737SRavi Kumar switch (phy_data->sfp_base) { 483a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_T: 484a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_CX: 485a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_CR: 486a5c72737SRavi Kumar pdata->phy.advertising |= ADVERTISED_TP; 487a5c72737SRavi Kumar break; 488a5c72737SRavi Kumar default: 489a5c72737SRavi Kumar pdata->phy.advertising |= ADVERTISED_FIBRE; 490a5c72737SRavi Kumar } 491a5c72737SRavi Kumar 492a5c72737SRavi Kumar switch (phy_data->sfp_speed) { 493a5c72737SRavi Kumar case AXGBE_SFP_SPEED_100_1000: 494*1f9d2d3aSVenkat Kumar Ande if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10) 495*1f9d2d3aSVenkat Kumar Ande pdata->phy.advertising |= ADVERTISED_10baseT_Full; 496a5c72737SRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) 497a5c72737SRavi Kumar pdata->phy.advertising |= ADVERTISED_100baseT_Full; 498a5c72737SRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) 499a5c72737SRavi Kumar pdata->phy.advertising |= ADVERTISED_1000baseT_Full; 500a5c72737SRavi Kumar break; 501a5c72737SRavi Kumar case AXGBE_SFP_SPEED_1000: 502a5c72737SRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) 503a5c72737SRavi Kumar pdata->phy.advertising |= ADVERTISED_1000baseT_Full; 504a5c72737SRavi Kumar break; 505a5c72737SRavi Kumar case AXGBE_SFP_SPEED_10000: 506a5c72737SRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) 507a5c72737SRavi Kumar pdata->phy.advertising |= ADVERTISED_10000baseT_Full; 508a5c72737SRavi Kumar break; 509a5c72737SRavi Kumar default: 510a5c72737SRavi Kumar /* Choose the fastest supported speed */ 511a5c72737SRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) 512a5c72737SRavi Kumar pdata->phy.advertising |= ADVERTISED_10000baseT_Full; 513a5c72737SRavi Kumar else if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) 514a5c72737SRavi Kumar pdata->phy.advertising |= ADVERTISED_1000baseT_Full; 515a5c72737SRavi Kumar else if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) 516a5c72737SRavi Kumar pdata->phy.advertising |= ADVERTISED_100baseT_Full; 517*1f9d2d3aSVenkat Kumar Ande else if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10) 518*1f9d2d3aSVenkat Kumar Ande pdata->phy.advertising |= ADVERTISED_10baseT_Full; 519a5c72737SRavi Kumar } 520a5c72737SRavi Kumar } 521a5c72737SRavi Kumar 522a5c72737SRavi Kumar static bool axgbe_phy_sfp_bit_rate(struct axgbe_sfp_eeprom *sfp_eeprom, 523a5c72737SRavi Kumar enum axgbe_sfp_speed sfp_speed) 524a5c72737SRavi Kumar { 525b5587a39SVenkat Kumar Ande u8 *sfp_base, min; 526a5c72737SRavi Kumar 527a5c72737SRavi Kumar sfp_base = sfp_eeprom->base; 528a5c72737SRavi Kumar 529a5c72737SRavi Kumar switch (sfp_speed) { 530a5c72737SRavi Kumar case AXGBE_SFP_SPEED_1000: 531a5c72737SRavi Kumar min = AXGBE_SFP_BASE_BR_1GBE_MIN; 532a5c72737SRavi Kumar break; 533a5c72737SRavi Kumar case AXGBE_SFP_SPEED_10000: 534a5c72737SRavi Kumar min = AXGBE_SFP_BASE_BR_10GBE_MIN; 535a5c72737SRavi Kumar break; 536a5c72737SRavi Kumar default: 537a5c72737SRavi Kumar return false; 538a5c72737SRavi Kumar } 539a5c72737SRavi Kumar 540b5587a39SVenkat Kumar Ande return sfp_base[AXGBE_SFP_BASE_BR] >= min; 541a5c72737SRavi Kumar } 542a5c72737SRavi Kumar 543a5c72737SRavi Kumar static void axgbe_phy_sfp_external_phy(struct axgbe_port *pdata) 544a5c72737SRavi Kumar { 545a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 546a5c72737SRavi Kumar 547a5c72737SRavi Kumar if (!phy_data->sfp_changed) 548a5c72737SRavi Kumar return; 549a5c72737SRavi Kumar 550a5c72737SRavi Kumar phy_data->sfp_phy_avail = 0; 551a5c72737SRavi Kumar 552a5c72737SRavi Kumar if (phy_data->sfp_base != AXGBE_SFP_BASE_1000_T) 553a5c72737SRavi Kumar return; 554a5c72737SRavi Kumar } 555a5c72737SRavi Kumar 556a5c72737SRavi Kumar static bool axgbe_phy_belfuse_parse_quirks(struct axgbe_port *pdata) 557a5c72737SRavi Kumar { 558a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 559a5c72737SRavi Kumar struct axgbe_sfp_eeprom *sfp_eeprom = &phy_data->sfp_eeprom; 560a5c72737SRavi Kumar 561a5c72737SRavi Kumar if (memcmp(&sfp_eeprom->base[AXGBE_SFP_BASE_VENDOR_NAME], 56227578231SAndy Green AXGBE_BEL_FUSE_VENDOR, strlen(AXGBE_BEL_FUSE_VENDOR))) 563a5c72737SRavi Kumar return false; 564a770d00aSVenkat Kumar Ande /* For Bel-Fuse, use the extra AN flag */ 565a770d00aSVenkat Kumar Ande pdata->an_again = 1; 566a5c72737SRavi Kumar 5673abfda0fSVenkat Kumar Ande /* Reset PHY - wait for self-clearing reset bit to clear */ 5683abfda0fSVenkat Kumar Ande pdata->phy_if.phy_impl.reset(pdata); 5693abfda0fSVenkat Kumar Ande 570a5c72737SRavi Kumar if (!memcmp(&sfp_eeprom->base[AXGBE_SFP_BASE_VENDOR_PN], 57127578231SAndy Green AXGBE_BEL_FUSE_PARTNO, strlen(AXGBE_BEL_FUSE_PARTNO))) { 572a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_1000_SX; 573a5c72737SRavi Kumar phy_data->sfp_cable = AXGBE_SFP_CABLE_ACTIVE; 574a5c72737SRavi Kumar phy_data->sfp_speed = AXGBE_SFP_SPEED_1000; 575a5c72737SRavi Kumar return true; 576a5c72737SRavi Kumar } 577a5c72737SRavi Kumar 578a5c72737SRavi Kumar return false; 579a5c72737SRavi Kumar } 580a5c72737SRavi Kumar 581a5c72737SRavi Kumar static bool axgbe_phy_sfp_parse_quirks(struct axgbe_port *pdata) 582a5c72737SRavi Kumar { 583a5c72737SRavi Kumar if (axgbe_phy_belfuse_parse_quirks(pdata)) 584a5c72737SRavi Kumar return true; 585a5c72737SRavi Kumar 586a5c72737SRavi Kumar return false; 587a5c72737SRavi Kumar } 588a5c72737SRavi Kumar 589a5c72737SRavi Kumar static void axgbe_phy_sfp_parse_eeprom(struct axgbe_port *pdata) 590a5c72737SRavi Kumar { 591a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 592a5c72737SRavi Kumar struct axgbe_sfp_eeprom *sfp_eeprom = &phy_data->sfp_eeprom; 593a5c72737SRavi Kumar uint8_t *sfp_base; 594a5c72737SRavi Kumar 595a5c72737SRavi Kumar sfp_base = sfp_eeprom->base; 596a5c72737SRavi Kumar 597a5c72737SRavi Kumar if (sfp_base[AXGBE_SFP_BASE_ID] != AXGBE_SFP_ID_SFP) 598a5c72737SRavi Kumar return; 599a5c72737SRavi Kumar 600a5c72737SRavi Kumar if (sfp_base[AXGBE_SFP_BASE_EXT_ID] != AXGBE_SFP_EXT_ID_SFP) 601a5c72737SRavi Kumar return; 602a5c72737SRavi Kumar 603936e294cSGirish Nandibasappa axgbe_phy_sfp_parse_quirks(pdata); 604a5c72737SRavi Kumar 6054823ccdbSVenkat Kumar Ande /* Assume FIBER cable unless told otherwise */ 606a5c72737SRavi Kumar if (sfp_base[AXGBE_SFP_BASE_CABLE] & AXGBE_SFP_BASE_CABLE_PASSIVE) { 607a5c72737SRavi Kumar phy_data->sfp_cable = AXGBE_SFP_CABLE_PASSIVE; 608a5c72737SRavi Kumar phy_data->sfp_cable_len = sfp_base[AXGBE_SFP_BASE_CU_CABLE_LEN]; 6094823ccdbSVenkat Kumar Ande } else if (sfp_base[AXGBE_SFP_BASE_CABLE] & AXGBE_SFP_BASE_CABLE_ACTIVE) { 610a5c72737SRavi Kumar phy_data->sfp_cable = AXGBE_SFP_CABLE_ACTIVE; 6114823ccdbSVenkat Kumar Ande } else { 6124823ccdbSVenkat Kumar Ande phy_data->sfp_cable = AXGBE_SFP_CABLE_FIBER; 613a5c72737SRavi Kumar } 614a5c72737SRavi Kumar 615a5c72737SRavi Kumar /* Determine the type of SFP */ 6164823ccdbSVenkat Kumar Ande if (phy_data->sfp_cable != AXGBE_SFP_CABLE_FIBER && 6174eefb1b1SVenkat Kumar Ande axgbe_phy_sfp_bit_rate(sfp_eeprom, AXGBE_SFP_SPEED_10000)) 6184eefb1b1SVenkat Kumar Ande phy_data->sfp_base = AXGBE_SFP_BASE_10000_CR; 6194eefb1b1SVenkat Kumar Ande else if (sfp_base[AXGBE_SFP_BASE_10GBE_CC] & AXGBE_SFP_BASE_10GBE_CC_SR) 620a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_10000_SR; 621a5c72737SRavi Kumar else if (sfp_base[AXGBE_SFP_BASE_10GBE_CC] & AXGBE_SFP_BASE_10GBE_CC_LR) 622a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_10000_LR; 623a5c72737SRavi Kumar else if (sfp_base[AXGBE_SFP_BASE_10GBE_CC] & 624a5c72737SRavi Kumar AXGBE_SFP_BASE_10GBE_CC_LRM) 625a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_10000_LRM; 626a5c72737SRavi Kumar else if (sfp_base[AXGBE_SFP_BASE_10GBE_CC] & AXGBE_SFP_BASE_10GBE_CC_ER) 627a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_10000_ER; 628a5c72737SRavi Kumar else if (sfp_base[AXGBE_SFP_BASE_1GBE_CC] & AXGBE_SFP_BASE_1GBE_CC_SX) 629a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_1000_SX; 630a5c72737SRavi Kumar else if (sfp_base[AXGBE_SFP_BASE_1GBE_CC] & AXGBE_SFP_BASE_1GBE_CC_LX) 631a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_1000_LX; 632a5c72737SRavi Kumar else if (sfp_base[AXGBE_SFP_BASE_1GBE_CC] & AXGBE_SFP_BASE_1GBE_CC_CX) 633a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_1000_CX; 634a5c72737SRavi Kumar else if (sfp_base[AXGBE_SFP_BASE_1GBE_CC] & AXGBE_SFP_BASE_1GBE_CC_T) 635a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_1000_T; 636a5c72737SRavi Kumar 637a5c72737SRavi Kumar switch (phy_data->sfp_base) { 638a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_T: 639a5c72737SRavi Kumar phy_data->sfp_speed = AXGBE_SFP_SPEED_100_1000; 640a5c72737SRavi Kumar break; 641a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_SX: 642a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_LX: 643a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_CX: 644a5c72737SRavi Kumar phy_data->sfp_speed = AXGBE_SFP_SPEED_1000; 645a5c72737SRavi Kumar break; 646a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_SR: 647a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_LR: 648a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_LRM: 649a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_ER: 650a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_CR: 651a5c72737SRavi Kumar phy_data->sfp_speed = AXGBE_SFP_SPEED_10000; 652a5c72737SRavi Kumar break; 653a5c72737SRavi Kumar default: 654a5c72737SRavi Kumar break; 655a5c72737SRavi Kumar } 656a5c72737SRavi Kumar } 657a5c72737SRavi Kumar 658a5c72737SRavi Kumar static bool axgbe_phy_sfp_verify_eeprom(uint8_t cc_in, uint8_t *buf, 659a5c72737SRavi Kumar unsigned int len) 660a5c72737SRavi Kumar { 661a5c72737SRavi Kumar uint8_t cc; 662a5c72737SRavi Kumar 663a5c72737SRavi Kumar for (cc = 0; len; buf++, len--) 664a5c72737SRavi Kumar cc += *buf; 665a5c72737SRavi Kumar 666aca000c0SVenkat Kumar Ande return cc == cc_in; 667a5c72737SRavi Kumar } 668a5c72737SRavi Kumar 669a5c72737SRavi Kumar static int axgbe_phy_sfp_read_eeprom(struct axgbe_port *pdata) 670a5c72737SRavi Kumar { 671a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 672a5c72737SRavi Kumar struct axgbe_sfp_eeprom sfp_eeprom; 673a5c72737SRavi Kumar uint8_t eeprom_addr; 674a5c72737SRavi Kumar int ret; 675a5c72737SRavi Kumar 676a5c72737SRavi Kumar ret = axgbe_phy_sfp_get_mux(pdata); 677a5c72737SRavi Kumar if (ret) { 678a5c72737SRavi Kumar PMD_DRV_LOG(ERR, "I2C error setting SFP MUX\n"); 679a5c72737SRavi Kumar return ret; 680a5c72737SRavi Kumar } 681a5c72737SRavi Kumar 682a5c72737SRavi Kumar /* Read the SFP serial ID eeprom */ 683a5c72737SRavi Kumar eeprom_addr = 0; 684a5c72737SRavi Kumar ret = axgbe_phy_i2c_read(pdata, AXGBE_SFP_SERIAL_ID_ADDRESS, 685a5c72737SRavi Kumar &eeprom_addr, sizeof(eeprom_addr), 686a5c72737SRavi Kumar &sfp_eeprom, sizeof(sfp_eeprom)); 687a5c72737SRavi Kumar if (ret) { 688a5c72737SRavi Kumar PMD_DRV_LOG(ERR, "I2C error reading SFP EEPROM\n"); 689a5c72737SRavi Kumar goto put; 690a5c72737SRavi Kumar } 691a5c72737SRavi Kumar 692a5c72737SRavi Kumar /* Validate the contents read */ 693a5c72737SRavi Kumar if (!axgbe_phy_sfp_verify_eeprom(sfp_eeprom.base[AXGBE_SFP_BASE_CC], 694a5c72737SRavi Kumar sfp_eeprom.base, 695a5c72737SRavi Kumar sizeof(sfp_eeprom.base) - 1)) { 696a5c72737SRavi Kumar ret = -EINVAL; 697a5c72737SRavi Kumar goto put; 698a5c72737SRavi Kumar } 699a5c72737SRavi Kumar 700a5c72737SRavi Kumar if (!axgbe_phy_sfp_verify_eeprom(sfp_eeprom.extd[AXGBE_SFP_EXTD_CC], 701a5c72737SRavi Kumar sfp_eeprom.extd, 702a5c72737SRavi Kumar sizeof(sfp_eeprom.extd) - 1)) { 703a5c72737SRavi Kumar ret = -EINVAL; 704a5c72737SRavi Kumar goto put; 705a5c72737SRavi Kumar } 706a5c72737SRavi Kumar 707a5c72737SRavi Kumar /* Check for an added or changed SFP */ 708a5c72737SRavi Kumar if (memcmp(&phy_data->sfp_eeprom, &sfp_eeprom, sizeof(sfp_eeprom))) { 709a5c72737SRavi Kumar phy_data->sfp_changed = 1; 710a5c72737SRavi Kumar memcpy(&phy_data->sfp_eeprom, &sfp_eeprom, sizeof(sfp_eeprom)); 711a5c72737SRavi Kumar } else { 712a5c72737SRavi Kumar phy_data->sfp_changed = 0; 713a5c72737SRavi Kumar } 714a5c72737SRavi Kumar 715a5c72737SRavi Kumar put: 716a5c72737SRavi Kumar axgbe_phy_sfp_put_mux(pdata); 717a5c72737SRavi Kumar 718a5c72737SRavi Kumar return ret; 719a5c72737SRavi Kumar } 720a5c72737SRavi Kumar 721a5c72737SRavi Kumar static void axgbe_phy_sfp_signals(struct axgbe_port *pdata) 722a5c72737SRavi Kumar { 723a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 724a5c72737SRavi Kumar unsigned int gpio_input; 725a5c72737SRavi Kumar u8 gpio_reg, gpio_ports[2]; 726a5c72737SRavi Kumar int ret; 727a5c72737SRavi Kumar 728a5c72737SRavi Kumar /* Read the input port registers */ 729a5c72737SRavi Kumar gpio_reg = 0; 730a5c72737SRavi Kumar ret = axgbe_phy_i2c_read(pdata, phy_data->sfp_gpio_address, 731a5c72737SRavi Kumar &gpio_reg, sizeof(gpio_reg), 732a5c72737SRavi Kumar gpio_ports, sizeof(gpio_ports)); 733a5c72737SRavi Kumar if (ret) { 734a5c72737SRavi Kumar PMD_DRV_LOG(ERR, "I2C error reading SFP GPIOs\n"); 735a5c72737SRavi Kumar return; 736a5c72737SRavi Kumar } 737a5c72737SRavi Kumar 738a5c72737SRavi Kumar gpio_input = (gpio_ports[1] << 8) | gpio_ports[0]; 739a5c72737SRavi Kumar 740a5c72737SRavi Kumar if (phy_data->sfp_gpio_mask & AXGBE_GPIO_NO_MOD_ABSENT) { 741a5c72737SRavi Kumar /* No GPIO, just assume the module is present for now */ 742a5c72737SRavi Kumar phy_data->sfp_mod_absent = 0; 743a5c72737SRavi Kumar } else { 744a5c72737SRavi Kumar if (!(gpio_input & (1 << phy_data->sfp_gpio_mod_absent))) 745a5c72737SRavi Kumar phy_data->sfp_mod_absent = 0; 746a5c72737SRavi Kumar } 747a5c72737SRavi Kumar 748a5c72737SRavi Kumar if (!(phy_data->sfp_gpio_mask & AXGBE_GPIO_NO_RX_LOS) && 749a5c72737SRavi Kumar (gpio_input & (1 << phy_data->sfp_gpio_rx_los))) 750a5c72737SRavi Kumar phy_data->sfp_rx_los = 1; 751a5c72737SRavi Kumar 752a5c72737SRavi Kumar if (!(phy_data->sfp_gpio_mask & AXGBE_GPIO_NO_TX_FAULT) && 753a5c72737SRavi Kumar (gpio_input & (1 << phy_data->sfp_gpio_tx_fault))) 754a5c72737SRavi Kumar phy_data->sfp_tx_fault = 1; 755a5c72737SRavi Kumar } 756a5c72737SRavi Kumar 757a5c72737SRavi Kumar static void axgbe_phy_sfp_mod_absent(struct axgbe_port *pdata) 758a5c72737SRavi Kumar { 759a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 760a5c72737SRavi Kumar 761a5c72737SRavi Kumar phy_data->sfp_mod_absent = 1; 762a5c72737SRavi Kumar phy_data->sfp_phy_avail = 0; 763a5c72737SRavi Kumar memset(&phy_data->sfp_eeprom, 0, sizeof(phy_data->sfp_eeprom)); 764a5c72737SRavi Kumar } 765a5c72737SRavi Kumar 766a5c72737SRavi Kumar static void axgbe_phy_sfp_reset(struct axgbe_phy_data *phy_data) 767a5c72737SRavi Kumar { 768a5c72737SRavi Kumar phy_data->sfp_rx_los = 0; 769a5c72737SRavi Kumar phy_data->sfp_tx_fault = 0; 770a5c72737SRavi Kumar phy_data->sfp_mod_absent = 1; 771a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_UNKNOWN; 772a5c72737SRavi Kumar phy_data->sfp_cable = AXGBE_SFP_CABLE_UNKNOWN; 773a5c72737SRavi Kumar phy_data->sfp_speed = AXGBE_SFP_SPEED_UNKNOWN; 774a5c72737SRavi Kumar } 775a5c72737SRavi Kumar 7764216cdc0SChandu Babu N static const char *axgbe_base_as_string(enum axgbe_sfp_base sfp_base) 7774216cdc0SChandu Babu N { 7784216cdc0SChandu Babu N switch (sfp_base) { 7794216cdc0SChandu Babu N case AXGBE_SFP_BASE_1000_T: 7804216cdc0SChandu Babu N return "1G_T"; 7814216cdc0SChandu Babu N case AXGBE_SFP_BASE_1000_SX: 7824216cdc0SChandu Babu N return "1G_SX"; 7834216cdc0SChandu Babu N case AXGBE_SFP_BASE_1000_LX: 7844216cdc0SChandu Babu N return "1G_LX"; 7854216cdc0SChandu Babu N case AXGBE_SFP_BASE_1000_CX: 7864216cdc0SChandu Babu N return "1G_CX"; 7874216cdc0SChandu Babu N case AXGBE_SFP_BASE_10000_SR: 7884216cdc0SChandu Babu N return "10G_SR"; 7894216cdc0SChandu Babu N case AXGBE_SFP_BASE_10000_LR: 7904216cdc0SChandu Babu N return "10G_LR"; 7914216cdc0SChandu Babu N case AXGBE_SFP_BASE_10000_LRM: 7924216cdc0SChandu Babu N return "10G_LRM"; 7934216cdc0SChandu Babu N case AXGBE_SFP_BASE_10000_ER: 7944216cdc0SChandu Babu N return "10G_ER"; 7954216cdc0SChandu Babu N case AXGBE_SFP_BASE_10000_CR: 7964216cdc0SChandu Babu N return "10G_CR"; 7974216cdc0SChandu Babu N default: 7984216cdc0SChandu Babu N return "Unknown"; 7994216cdc0SChandu Babu N } 8004216cdc0SChandu Babu N } 8014216cdc0SChandu Babu N 802a5c72737SRavi Kumar static void axgbe_phy_sfp_detect(struct axgbe_port *pdata) 803a5c72737SRavi Kumar { 804a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 805a5c72737SRavi Kumar int ret; 806a5c72737SRavi Kumar 807a770d00aSVenkat Kumar Ande /* Clear the extra AN flag */ 808a770d00aSVenkat Kumar Ande pdata->an_again = 0; 809a770d00aSVenkat Kumar Ande 810a5c72737SRavi Kumar /* Reset the SFP signals and info */ 811a5c72737SRavi Kumar axgbe_phy_sfp_reset(phy_data); 812a5c72737SRavi Kumar 813a5c72737SRavi Kumar ret = axgbe_phy_get_comm_ownership(pdata); 814a5c72737SRavi Kumar if (ret) 815a5c72737SRavi Kumar return; 816a5c72737SRavi Kumar 817a5c72737SRavi Kumar /* Read the SFP signals and check for module presence */ 818a5c72737SRavi Kumar axgbe_phy_sfp_signals(pdata); 819a5c72737SRavi Kumar if (phy_data->sfp_mod_absent) { 820a5c72737SRavi Kumar axgbe_phy_sfp_mod_absent(pdata); 821a5c72737SRavi Kumar goto put; 822a5c72737SRavi Kumar } 823a5c72737SRavi Kumar 824a5c72737SRavi Kumar ret = axgbe_phy_sfp_read_eeprom(pdata); 825a5c72737SRavi Kumar if (ret) { 826a5c72737SRavi Kumar /* Treat any error as if there isn't an SFP plugged in */ 827a5c72737SRavi Kumar axgbe_phy_sfp_reset(phy_data); 828a5c72737SRavi Kumar axgbe_phy_sfp_mod_absent(pdata); 829a5c72737SRavi Kumar goto put; 830a5c72737SRavi Kumar } 831a5c72737SRavi Kumar 832a5c72737SRavi Kumar axgbe_phy_sfp_parse_eeprom(pdata); 833a5c72737SRavi Kumar axgbe_phy_sfp_external_phy(pdata); 834a5c72737SRavi Kumar 8354216cdc0SChandu Babu N PMD_DRV_LOG(DEBUG, "SFP Base: %s\n", 8364216cdc0SChandu Babu N axgbe_base_as_string(phy_data->sfp_base)); 8374216cdc0SChandu Babu N 838a5c72737SRavi Kumar put: 839a5c72737SRavi Kumar axgbe_phy_sfp_phy_settings(pdata); 840a5c72737SRavi Kumar axgbe_phy_put_comm_ownership(pdata); 841a5c72737SRavi Kumar } 842a5c72737SRavi Kumar 843a5c72737SRavi Kumar static void axgbe_phy_phydev_flowctrl(struct axgbe_port *pdata) 844a5c72737SRavi Kumar { 845a5c72737SRavi Kumar pdata->phy.tx_pause = 0; 846a5c72737SRavi Kumar pdata->phy.rx_pause = 0; 847a5c72737SRavi Kumar } 848a5c72737SRavi Kumar 849a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_an73_redrv_outcome(struct axgbe_port *pdata) 850a5c72737SRavi Kumar { 851a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 852a5c72737SRavi Kumar enum axgbe_mode mode; 853a5c72737SRavi Kumar unsigned int ad_reg, lp_reg; 854a5c72737SRavi Kumar 855a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_Autoneg; 856a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_Backplane; 857a5c72737SRavi Kumar 858a5c72737SRavi Kumar /* Use external PHY to determine flow control */ 859a5c72737SRavi Kumar if (pdata->phy.pause_autoneg) 860a5c72737SRavi Kumar axgbe_phy_phydev_flowctrl(pdata); 861a5c72737SRavi Kumar 862a5c72737SRavi Kumar /* Compare Advertisement and Link Partner register 2 */ 863a5c72737SRavi Kumar ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1); 864a5c72737SRavi Kumar lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1); 865a5c72737SRavi Kumar if (lp_reg & 0x80) 866a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full; 867a5c72737SRavi Kumar if (lp_reg & 0x20) 868a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full; 869a5c72737SRavi Kumar 870a5c72737SRavi Kumar ad_reg &= lp_reg; 871a5c72737SRavi Kumar if (ad_reg & 0x80) { 872a5c72737SRavi Kumar switch (phy_data->port_mode) { 873a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 874443ab5aaSSelwin Sebastian case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG: 875a5c72737SRavi Kumar mode = AXGBE_MODE_KR; 876a5c72737SRavi Kumar break; 877a5c72737SRavi Kumar default: 878a5c72737SRavi Kumar mode = AXGBE_MODE_SFI; 879a5c72737SRavi Kumar break; 880a5c72737SRavi Kumar } 881a5c72737SRavi Kumar } else if (ad_reg & 0x20) { 882a5c72737SRavi Kumar switch (phy_data->port_mode) { 883a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 884443ab5aaSSelwin Sebastian case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG: 885a5c72737SRavi Kumar mode = AXGBE_MODE_KX_1000; 886a5c72737SRavi Kumar break; 887a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 888a5c72737SRavi Kumar mode = AXGBE_MODE_X; 889a5c72737SRavi Kumar break; 890a5c72737SRavi Kumar case AXGBE_PORT_MODE_SFP: 891a5c72737SRavi Kumar switch (phy_data->sfp_base) { 892a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_T: 893a5c72737SRavi Kumar mode = AXGBE_MODE_SGMII_1000; 894a5c72737SRavi Kumar break; 895a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_SX: 896a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_LX: 897a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_CX: 898a5c72737SRavi Kumar default: 899a5c72737SRavi Kumar mode = AXGBE_MODE_X; 900a5c72737SRavi Kumar break; 901a5c72737SRavi Kumar } 902a5c72737SRavi Kumar break; 903a5c72737SRavi Kumar default: 904a5c72737SRavi Kumar mode = AXGBE_MODE_SGMII_1000; 905a5c72737SRavi Kumar break; 906a5c72737SRavi Kumar } 907a5c72737SRavi Kumar } else { 908a5c72737SRavi Kumar mode = AXGBE_MODE_UNKNOWN; 909a5c72737SRavi Kumar } 910a5c72737SRavi Kumar 911a5c72737SRavi Kumar /* Compare Advertisement and Link Partner register 3 */ 912a5c72737SRavi Kumar ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2); 913a5c72737SRavi Kumar lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2); 914a5c72737SRavi Kumar if (lp_reg & 0xc000) 915a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC; 916a5c72737SRavi Kumar 917a5c72737SRavi Kumar return mode; 918a5c72737SRavi Kumar } 919a5c72737SRavi Kumar 920a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_an73_outcome(struct axgbe_port *pdata) 921a5c72737SRavi Kumar { 922a5c72737SRavi Kumar enum axgbe_mode mode; 923a5c72737SRavi Kumar unsigned int ad_reg, lp_reg; 924a5c72737SRavi Kumar 925a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_Autoneg; 926a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_Backplane; 927a5c72737SRavi Kumar 928a5c72737SRavi Kumar /* Compare Advertisement and Link Partner register 1 */ 929a5c72737SRavi Kumar ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE); 930a5c72737SRavi Kumar lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA); 931a5c72737SRavi Kumar if (lp_reg & 0x400) 932a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_Pause; 933a5c72737SRavi Kumar if (lp_reg & 0x800) 934a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause; 935a5c72737SRavi Kumar 936a5c72737SRavi Kumar if (pdata->phy.pause_autoneg) { 937a5c72737SRavi Kumar /* Set flow control based on auto-negotiation result */ 938a5c72737SRavi Kumar pdata->phy.tx_pause = 0; 939a5c72737SRavi Kumar pdata->phy.rx_pause = 0; 940a5c72737SRavi Kumar 941a5c72737SRavi Kumar if (ad_reg & lp_reg & 0x400) { 942a5c72737SRavi Kumar pdata->phy.tx_pause = 1; 943a5c72737SRavi Kumar pdata->phy.rx_pause = 1; 944a5c72737SRavi Kumar } else if (ad_reg & lp_reg & 0x800) { 945a5c72737SRavi Kumar if (ad_reg & 0x400) 946a5c72737SRavi Kumar pdata->phy.rx_pause = 1; 947a5c72737SRavi Kumar else if (lp_reg & 0x400) 948a5c72737SRavi Kumar pdata->phy.tx_pause = 1; 949a5c72737SRavi Kumar } 950a5c72737SRavi Kumar } 951a5c72737SRavi Kumar 952a5c72737SRavi Kumar /* Compare Advertisement and Link Partner register 2 */ 953a5c72737SRavi Kumar ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1); 954a5c72737SRavi Kumar lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1); 955a5c72737SRavi Kumar if (lp_reg & 0x80) 956a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full; 957a5c72737SRavi Kumar if (lp_reg & 0x20) 958a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full; 959a5c72737SRavi Kumar 960a5c72737SRavi Kumar ad_reg &= lp_reg; 961a5c72737SRavi Kumar if (ad_reg & 0x80) 962a5c72737SRavi Kumar mode = AXGBE_MODE_KR; 963a5c72737SRavi Kumar else if (ad_reg & 0x20) 964a5c72737SRavi Kumar mode = AXGBE_MODE_KX_1000; 965a5c72737SRavi Kumar else 966a5c72737SRavi Kumar mode = AXGBE_MODE_UNKNOWN; 967a5c72737SRavi Kumar 968a5c72737SRavi Kumar /* Compare Advertisement and Link Partner register 3 */ 969a5c72737SRavi Kumar ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2); 970a5c72737SRavi Kumar lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2); 971a5c72737SRavi Kumar if (lp_reg & 0xc000) 972a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC; 973a5c72737SRavi Kumar 974a5c72737SRavi Kumar return mode; 975a5c72737SRavi Kumar } 976a5c72737SRavi Kumar 977102b6ec3SGirish Nandibasappa static enum axgbe_mode axgbe_phy_an37_sgmii_outcome(struct axgbe_port *pdata) 978102b6ec3SGirish Nandibasappa { 979102b6ec3SGirish Nandibasappa enum axgbe_mode mode; 980102b6ec3SGirish Nandibasappa 981102b6ec3SGirish Nandibasappa pdata->phy.lp_advertising |= ADVERTISED_Autoneg; 982102b6ec3SGirish Nandibasappa pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Full; 983102b6ec3SGirish Nandibasappa 984102b6ec3SGirish Nandibasappa if (pdata->phy.pause_autoneg) 985102b6ec3SGirish Nandibasappa axgbe_phy_phydev_flowctrl(pdata); 986102b6ec3SGirish Nandibasappa 987102b6ec3SGirish Nandibasappa switch (pdata->an_status & AXGBE_SGMII_AN_LINK_SPEED) { 988*1f9d2d3aSVenkat Kumar Ande case AXGBE_SGMII_AN_LINK_SPEED_10: 989*1f9d2d3aSVenkat Kumar Ande if (pdata->an_status & AXGBE_SGMII_AN_LINK_DUPLEX) { 990*1f9d2d3aSVenkat Kumar Ande pdata->phy.lp_advertising |= ADVERTISED_10baseT_Full; 991*1f9d2d3aSVenkat Kumar Ande mode = AXGBE_MODE_SGMII_10; 992*1f9d2d3aSVenkat Kumar Ande } else { 993*1f9d2d3aSVenkat Kumar Ande mode = AXGBE_MODE_UNKNOWN; 994*1f9d2d3aSVenkat Kumar Ande } 995*1f9d2d3aSVenkat Kumar Ande break; 996102b6ec3SGirish Nandibasappa case AXGBE_SGMII_AN_LINK_SPEED_100: 997102b6ec3SGirish Nandibasappa if (pdata->an_status & AXGBE_SGMII_AN_LINK_DUPLEX) { 998102b6ec3SGirish Nandibasappa pdata->phy.lp_advertising |= ADVERTISED_100baseT_Full; 999102b6ec3SGirish Nandibasappa mode = AXGBE_MODE_SGMII_100; 1000102b6ec3SGirish Nandibasappa } else { 1001102b6ec3SGirish Nandibasappa mode = AXGBE_MODE_UNKNOWN; 1002102b6ec3SGirish Nandibasappa } 1003102b6ec3SGirish Nandibasappa break; 1004102b6ec3SGirish Nandibasappa case AXGBE_SGMII_AN_LINK_SPEED_1000: 1005102b6ec3SGirish Nandibasappa if (pdata->an_status & AXGBE_SGMII_AN_LINK_DUPLEX) { 1006102b6ec3SGirish Nandibasappa pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Full; 1007102b6ec3SGirish Nandibasappa mode = AXGBE_MODE_SGMII_1000; 1008102b6ec3SGirish Nandibasappa } else { 1009102b6ec3SGirish Nandibasappa /* Half-duplex not supported */ 1010102b6ec3SGirish Nandibasappa mode = AXGBE_MODE_UNKNOWN; 1011102b6ec3SGirish Nandibasappa } 1012102b6ec3SGirish Nandibasappa break; 1013102b6ec3SGirish Nandibasappa default: 1014102b6ec3SGirish Nandibasappa mode = AXGBE_MODE_UNKNOWN; 1015102b6ec3SGirish Nandibasappa break; 1016102b6ec3SGirish Nandibasappa } 1017102b6ec3SGirish Nandibasappa return mode; 1018102b6ec3SGirish Nandibasappa } 1019102b6ec3SGirish Nandibasappa 1020a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_an_outcome(struct axgbe_port *pdata) 1021a5c72737SRavi Kumar { 1022a5c72737SRavi Kumar switch (pdata->an_mode) { 1023a5c72737SRavi Kumar case AXGBE_AN_MODE_CL73: 1024a5c72737SRavi Kumar return axgbe_phy_an73_outcome(pdata); 1025a5c72737SRavi Kumar case AXGBE_AN_MODE_CL73_REDRV: 1026a5c72737SRavi Kumar return axgbe_phy_an73_redrv_outcome(pdata); 1027a5c72737SRavi Kumar case AXGBE_AN_MODE_CL37: 1028a5c72737SRavi Kumar case AXGBE_AN_MODE_CL37_SGMII: 1029102b6ec3SGirish Nandibasappa return axgbe_phy_an37_sgmii_outcome(pdata); 1030a5c72737SRavi Kumar default: 1031a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1032a5c72737SRavi Kumar } 1033a5c72737SRavi Kumar } 1034a5c72737SRavi Kumar 1035a5c72737SRavi Kumar static unsigned int axgbe_phy_an_advertising(struct axgbe_port *pdata) 1036a5c72737SRavi Kumar { 1037a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1038a5c72737SRavi Kumar unsigned int advertising; 1039a5c72737SRavi Kumar 1040a5c72737SRavi Kumar /* Without a re-driver, just return current advertising */ 1041a5c72737SRavi Kumar if (!phy_data->redrv) 1042a5c72737SRavi Kumar return pdata->phy.advertising; 1043a5c72737SRavi Kumar 1044a5c72737SRavi Kumar /* With the KR re-driver we need to advertise a single speed */ 1045a5c72737SRavi Kumar advertising = pdata->phy.advertising; 1046a5c72737SRavi Kumar advertising &= ~ADVERTISED_1000baseKX_Full; 1047a5c72737SRavi Kumar advertising &= ~ADVERTISED_10000baseKR_Full; 1048a5c72737SRavi Kumar 1049a5c72737SRavi Kumar switch (phy_data->port_mode) { 1050a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 1051443ab5aaSSelwin Sebastian case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG: 1052a5c72737SRavi Kumar advertising |= ADVERTISED_10000baseKR_Full; 1053a5c72737SRavi Kumar break; 1054a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 1055a5c72737SRavi Kumar advertising |= ADVERTISED_1000baseKX_Full; 1056a5c72737SRavi Kumar break; 1057a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 1058a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 1059a5c72737SRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 1060a5c72737SRavi Kumar advertising |= ADVERTISED_1000baseKX_Full; 1061a5c72737SRavi Kumar break; 1062a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 1063a5c72737SRavi Kumar PMD_DRV_LOG(ERR, "10GBASE_T mode is not supported\n"); 1064a5c72737SRavi Kumar break; 1065a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 1066a5c72737SRavi Kumar advertising |= ADVERTISED_10000baseKR_Full; 1067a5c72737SRavi Kumar break; 1068a5c72737SRavi Kumar case AXGBE_PORT_MODE_SFP: 1069a5c72737SRavi Kumar switch (phy_data->sfp_base) { 1070a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_T: 1071a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_SX: 1072a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_LX: 1073a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_CX: 1074a5c72737SRavi Kumar advertising |= ADVERTISED_1000baseKX_Full; 1075a5c72737SRavi Kumar break; 1076a5c72737SRavi Kumar default: 1077a5c72737SRavi Kumar advertising |= ADVERTISED_10000baseKR_Full; 1078a5c72737SRavi Kumar break; 1079a5c72737SRavi Kumar } 1080a5c72737SRavi Kumar break; 1081a5c72737SRavi Kumar default: 1082a5c72737SRavi Kumar advertising |= ADVERTISED_10000baseKR_Full; 1083a5c72737SRavi Kumar break; 1084a5c72737SRavi Kumar } 1085a5c72737SRavi Kumar 1086a5c72737SRavi Kumar return advertising; 1087a5c72737SRavi Kumar } 1088a5c72737SRavi Kumar 1089a5c72737SRavi Kumar static int axgbe_phy_an_config(struct axgbe_port *pdata __rte_unused) 1090a5c72737SRavi Kumar { 1091a5c72737SRavi Kumar return 0; 1092a5c72737SRavi Kumar /* Dummy API since there is no case to support 10937be78d02SJosh Soref * external phy devices registered through kernel APIs 1094a5c72737SRavi Kumar */ 1095a5c72737SRavi Kumar } 1096a5c72737SRavi Kumar 1097a5c72737SRavi Kumar static enum axgbe_an_mode axgbe_phy_an_sfp_mode(struct axgbe_phy_data *phy_data) 1098a5c72737SRavi Kumar { 1099a5c72737SRavi Kumar switch (phy_data->sfp_base) { 1100a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_T: 1101a5c72737SRavi Kumar return AXGBE_AN_MODE_CL37_SGMII; 1102a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_SX: 1103a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_LX: 1104a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_CX: 1105a5c72737SRavi Kumar return AXGBE_AN_MODE_CL37; 1106a5c72737SRavi Kumar default: 1107a5c72737SRavi Kumar return AXGBE_AN_MODE_NONE; 1108a5c72737SRavi Kumar } 1109a5c72737SRavi Kumar } 1110a5c72737SRavi Kumar 1111a5c72737SRavi Kumar static enum axgbe_an_mode axgbe_phy_an_mode(struct axgbe_port *pdata) 1112a5c72737SRavi Kumar { 1113a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1114a5c72737SRavi Kumar 1115a5c72737SRavi Kumar /* A KR re-driver will always require CL73 AN */ 1116a5c72737SRavi Kumar if (phy_data->redrv) 1117a5c72737SRavi Kumar return AXGBE_AN_MODE_CL73_REDRV; 1118a5c72737SRavi Kumar 1119a5c72737SRavi Kumar switch (phy_data->port_mode) { 1120a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 1121a5c72737SRavi Kumar return AXGBE_AN_MODE_CL73; 1122443ab5aaSSelwin Sebastian case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG: 1123a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 1124a5c72737SRavi Kumar return AXGBE_AN_MODE_NONE; 1125a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 1126a5c72737SRavi Kumar return AXGBE_AN_MODE_CL37_SGMII; 1127a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 1128a5c72737SRavi Kumar return AXGBE_AN_MODE_CL37; 1129a5c72737SRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 1130a5c72737SRavi Kumar return AXGBE_AN_MODE_CL37_SGMII; 1131a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 1132a5c72737SRavi Kumar return AXGBE_AN_MODE_CL73; 1133a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 1134a5c72737SRavi Kumar return AXGBE_AN_MODE_NONE; 1135a5c72737SRavi Kumar case AXGBE_PORT_MODE_SFP: 1136a5c72737SRavi Kumar return axgbe_phy_an_sfp_mode(phy_data); 1137a5c72737SRavi Kumar default: 1138a5c72737SRavi Kumar return AXGBE_AN_MODE_NONE; 1139a5c72737SRavi Kumar } 1140a5c72737SRavi Kumar } 1141a5c72737SRavi Kumar 1142a5c72737SRavi Kumar static int axgbe_phy_set_redrv_mode_mdio(struct axgbe_port *pdata, 1143a5c72737SRavi Kumar enum axgbe_phy_redrv_mode mode) 1144a5c72737SRavi Kumar { 1145a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1146a5c72737SRavi Kumar u16 redrv_reg, redrv_val; 1147a5c72737SRavi Kumar 1148a5c72737SRavi Kumar redrv_reg = AXGBE_PHY_REDRV_MODE_REG + (phy_data->redrv_lane * 0x1000); 1149a5c72737SRavi Kumar redrv_val = (u16)mode; 1150a5c72737SRavi Kumar 1151a5c72737SRavi Kumar return pdata->hw_if.write_ext_mii_regs(pdata, phy_data->redrv_addr, 1152a5c72737SRavi Kumar redrv_reg, redrv_val); 1153a5c72737SRavi Kumar } 1154a5c72737SRavi Kumar 1155a5c72737SRavi Kumar static int axgbe_phy_set_redrv_mode_i2c(struct axgbe_port *pdata, 1156a5c72737SRavi Kumar enum axgbe_phy_redrv_mode mode) 1157a5c72737SRavi Kumar { 1158a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1159a5c72737SRavi Kumar unsigned int redrv_reg; 1160a5c72737SRavi Kumar int ret; 1161a5c72737SRavi Kumar 1162a5c72737SRavi Kumar /* Calculate the register to write */ 1163a5c72737SRavi Kumar redrv_reg = AXGBE_PHY_REDRV_MODE_REG + (phy_data->redrv_lane * 0x1000); 1164a5c72737SRavi Kumar 1165a5c72737SRavi Kumar ret = axgbe_phy_redrv_write(pdata, redrv_reg, mode); 1166a5c72737SRavi Kumar 1167a5c72737SRavi Kumar return ret; 1168a5c72737SRavi Kumar } 1169a5c72737SRavi Kumar 1170a5c72737SRavi Kumar static void axgbe_phy_set_redrv_mode(struct axgbe_port *pdata) 1171a5c72737SRavi Kumar { 1172a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1173a5c72737SRavi Kumar enum axgbe_phy_redrv_mode mode; 1174a5c72737SRavi Kumar int ret; 1175a5c72737SRavi Kumar 1176a5c72737SRavi Kumar if (!phy_data->redrv) 1177a5c72737SRavi Kumar return; 1178a5c72737SRavi Kumar 1179a5c72737SRavi Kumar mode = AXGBE_PHY_REDRV_MODE_CX; 1180a5c72737SRavi Kumar if ((phy_data->port_mode == AXGBE_PORT_MODE_SFP) && 1181a5c72737SRavi Kumar (phy_data->sfp_base != AXGBE_SFP_BASE_1000_CX) && 1182a5c72737SRavi Kumar (phy_data->sfp_base != AXGBE_SFP_BASE_10000_CR)) 1183a5c72737SRavi Kumar mode = AXGBE_PHY_REDRV_MODE_SR; 1184a5c72737SRavi Kumar 1185a5c72737SRavi Kumar ret = axgbe_phy_get_comm_ownership(pdata); 1186a5c72737SRavi Kumar if (ret) 1187a5c72737SRavi Kumar return; 1188a5c72737SRavi Kumar 1189a5c72737SRavi Kumar if (phy_data->redrv_if) 1190a5c72737SRavi Kumar axgbe_phy_set_redrv_mode_i2c(pdata, mode); 1191a5c72737SRavi Kumar else 1192a5c72737SRavi Kumar axgbe_phy_set_redrv_mode_mdio(pdata, mode); 1193a5c72737SRavi Kumar 1194a5c72737SRavi Kumar axgbe_phy_put_comm_ownership(pdata); 1195a5c72737SRavi Kumar } 1196a5c72737SRavi Kumar 1197cd48955bSSelwin Sebastian static void axgbe_phy_rx_reset(struct axgbe_port *pdata) 1198cd48955bSSelwin Sebastian { 1199cd48955bSSelwin Sebastian int reg; 1200cd48955bSSelwin Sebastian 1201cd48955bSSelwin Sebastian reg = XMDIO_READ_BITS(pdata, MDIO_MMD_PCS, MDIO_PCS_DIGITAL_STAT, 1202cd48955bSSelwin Sebastian XGBE_PCS_PSEQ_STATE_MASK); 1203cd48955bSSelwin Sebastian if (reg == XGBE_PCS_PSEQ_STATE_POWER_GOOD) { 1204cd48955bSSelwin Sebastian /* Mailbox command timed out, reset of RX block is required. 1205cd48955bSSelwin Sebastian * This can be done by asseting the reset bit and wait for 1206cd48955bSSelwin Sebastian * its compeletion. 1207cd48955bSSelwin Sebastian */ 1208cd48955bSSelwin Sebastian XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1, 1209cd48955bSSelwin Sebastian XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_ON); 1210cd48955bSSelwin Sebastian rte_delay_us(20); 1211cd48955bSSelwin Sebastian XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1, 1212cd48955bSSelwin Sebastian XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_OFF); 1213cd48955bSSelwin Sebastian rte_delay_us(45); 1214cd48955bSSelwin Sebastian PMD_DRV_LOG(ERR, "firmware mailbox reset performed\n"); 1215cd48955bSSelwin Sebastian } 1216cd48955bSSelwin Sebastian } 1217cd48955bSSelwin Sebastian 1218cd48955bSSelwin Sebastian 121909b0a36cSSelwin Sebastian static void axgbe_phy_pll_ctrl(struct axgbe_port *pdata, bool enable) 122009b0a36cSSelwin Sebastian { 12211c68b393SVenkat Kumar Ande /* PLL_CTRL feature needs to be enabled for fixed PHY modes (Non-Autoneg) only */ 12221c68b393SVenkat Kumar Ande if (pdata->phy.autoneg != AUTONEG_DISABLE) 12231c68b393SVenkat Kumar Ande return; 12241c68b393SVenkat Kumar Ande 122509b0a36cSSelwin Sebastian XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_MISC_CTRL0, 122609b0a36cSSelwin Sebastian XGBE_PMA_PLL_CTRL_MASK, 122709b0a36cSSelwin Sebastian enable ? XGBE_PMA_PLL_CTRL_SET 122809b0a36cSSelwin Sebastian : XGBE_PMA_PLL_CTRL_CLEAR); 122909b0a36cSSelwin Sebastian 123009b0a36cSSelwin Sebastian /* Wait for command to complete */ 123109b0a36cSSelwin Sebastian rte_delay_us(150); 123209b0a36cSSelwin Sebastian } 123309b0a36cSSelwin Sebastian 12340df8d8dfSSelwin Sebastian static void axgbe_phy_perform_ratechange(struct axgbe_port *pdata, 1235cf96031aSVenkat Kumar Ande enum axgbe_mb_cmd cmd, enum axgbe_mb_subcmd sub_cmd) 1236a5c72737SRavi Kumar { 12370df8d8dfSSelwin Sebastian unsigned int s0 = 0; 12380df8d8dfSSelwin Sebastian unsigned int wait; 123909b0a36cSSelwin Sebastian /* Clear the PLL so that it helps in power down sequence */ 124009b0a36cSSelwin Sebastian axgbe_phy_pll_ctrl(pdata, false); 124109b0a36cSSelwin Sebastian 12424216cdc0SChandu Babu N /* Log if a previous command did not complete */ 1243cd48955bSSelwin Sebastian if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) { 12444216cdc0SChandu Babu N PMD_DRV_LOG(NOTICE, "firmware mailbox not ready for command\n"); 1245cd48955bSSelwin Sebastian axgbe_phy_rx_reset(pdata); 1246cd48955bSSelwin Sebastian } 1247a5c72737SRavi Kumar 12480df8d8dfSSelwin Sebastian /* Construct the command */ 12490df8d8dfSSelwin Sebastian XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, cmd); 12500df8d8dfSSelwin Sebastian XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, sub_cmd); 12510df8d8dfSSelwin Sebastian 12520df8d8dfSSelwin Sebastian /* Issue the command */ 12530df8d8dfSSelwin Sebastian XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0); 12540df8d8dfSSelwin Sebastian XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0); 12550df8d8dfSSelwin Sebastian XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1); 1256a5c72737SRavi Kumar 1257a5c72737SRavi Kumar /* Wait for command to complete */ 1258a5c72737SRavi Kumar wait = AXGBE_RATECHANGE_COUNT; 1259a5c72737SRavi Kumar while (wait--) { 1260a5c72737SRavi Kumar if (!XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) 126109b0a36cSSelwin Sebastian goto reenable_pll; 1262a5c72737SRavi Kumar rte_delay_us(1500); 1263a5c72737SRavi Kumar } 1264cd48955bSSelwin Sebastian PMD_DRV_LOG(NOTICE, "firmware mailbox command did not complete\n"); 1265cd48955bSSelwin Sebastian /* Reset on error */ 1266cd48955bSSelwin Sebastian axgbe_phy_rx_reset(pdata); 126709b0a36cSSelwin Sebastian 126809b0a36cSSelwin Sebastian reenable_pll: 12691c68b393SVenkat Kumar Ande /* Enable PLL re-initialization, not needed for PHY Power Off and RRC cmds */ 1270cf96031aSVenkat Kumar Ande if (cmd != AXGBE_MB_CMD_POWER_OFF && 1271cf96031aSVenkat Kumar Ande cmd != AXGBE_MB_CMD_RRC) 127209b0a36cSSelwin Sebastian axgbe_phy_pll_ctrl(pdata, true); 127309b0a36cSSelwin Sebastian 12744216cdc0SChandu Babu N PMD_DRV_LOG(NOTICE, "firmware mailbox command did not complete\n"); 1275a5c72737SRavi Kumar } 1276a5c72737SRavi Kumar 1277a5c72737SRavi Kumar static void axgbe_phy_rrc(struct axgbe_port *pdata) 1278a5c72737SRavi Kumar { 1279a5c72737SRavi Kumar 1280a5c72737SRavi Kumar 1281a5c72737SRavi Kumar /* Receiver Reset Cycle */ 1282cf96031aSVenkat Kumar Ande axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_RRC, AXGBE_MB_SUBCMD_NONE); 12834216cdc0SChandu Babu N 12844216cdc0SChandu Babu N PMD_DRV_LOG(DEBUG, "receiver reset complete\n"); 1285a5c72737SRavi Kumar } 1286a5c72737SRavi Kumar 1287a5c72737SRavi Kumar static void axgbe_phy_power_off(struct axgbe_port *pdata) 1288a5c72737SRavi Kumar { 1289a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1290a5c72737SRavi Kumar 12910df8d8dfSSelwin Sebastian /* Power off */ 1292cf96031aSVenkat Kumar Ande axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_POWER_OFF, AXGBE_MB_SUBCMD_NONE); 1293a5c72737SRavi Kumar 1294a5c72737SRavi Kumar phy_data->cur_mode = AXGBE_MODE_UNKNOWN; 12954216cdc0SChandu Babu N 12964216cdc0SChandu Babu N PMD_DRV_LOG(DEBUG, "phy powered off\n"); 1297a5c72737SRavi Kumar } 1298a5c72737SRavi Kumar 1299a5c72737SRavi Kumar static void axgbe_phy_sfi_mode(struct axgbe_port *pdata) 1300a5c72737SRavi Kumar { 1301a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1302a5c72737SRavi Kumar 1303a5c72737SRavi Kumar axgbe_phy_set_redrv_mode(pdata); 1304a5c72737SRavi Kumar 1305a5c72737SRavi Kumar /* 10G/SFI */ 1306a5c72737SRavi Kumar if (phy_data->sfp_cable != AXGBE_SFP_CABLE_PASSIVE) { 1307cf96031aSVenkat Kumar Ande axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_SET_10G_SFI, 1308cf96031aSVenkat Kumar Ande AXGBE_MB_SUBCMD_ACTIVE); 1309a5c72737SRavi Kumar } else { 1310a5c72737SRavi Kumar if (phy_data->sfp_cable_len <= 1) 1311cf96031aSVenkat Kumar Ande axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_SET_10G_SFI, 1312cf96031aSVenkat Kumar Ande AXGBE_MB_SUBCMD_PASSIVE_1M); 1313a5c72737SRavi Kumar else if (phy_data->sfp_cable_len <= 3) 1314cf96031aSVenkat Kumar Ande axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_SET_10G_SFI, 1315cf96031aSVenkat Kumar Ande AXGBE_MB_SUBCMD_PASSIVE_3M); 1316a5c72737SRavi Kumar else 1317cf96031aSVenkat Kumar Ande axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_SET_10G_SFI, 1318cf96031aSVenkat Kumar Ande AXGBE_MB_SUBCMD_PASSIVE_OTHER); 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 */ 1333cf96031aSVenkat Kumar Ande axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_SET_10G_KR, 1334cf96031aSVenkat Kumar Ande AXGBE_MB_SUBCMD_NONE); 1335a5c72737SRavi Kumar phy_data->cur_mode = AXGBE_MODE_KR; 13364216cdc0SChandu Babu N 13374216cdc0SChandu Babu N PMD_DRV_LOG(DEBUG, "10GbE KR mode set\n"); 1338a5c72737SRavi Kumar } 1339a5c72737SRavi Kumar 1340936e294cSGirish Nandibasappa static void axgbe_phy_kx_2500_mode(struct axgbe_port *pdata) 1341936e294cSGirish Nandibasappa { 1342936e294cSGirish Nandibasappa struct axgbe_phy_data *phy_data = pdata->phy_data; 1343936e294cSGirish Nandibasappa 1344936e294cSGirish Nandibasappa axgbe_phy_set_redrv_mode(pdata); 13450df8d8dfSSelwin Sebastian 1346936e294cSGirish Nandibasappa /* 2.5G/KX */ 1347cf96031aSVenkat Kumar Ande axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_SET_2_5G, AXGBE_MB_SUBCMD_NONE); 1348936e294cSGirish Nandibasappa phy_data->cur_mode = AXGBE_MODE_KX_2500; 1349936e294cSGirish Nandibasappa } 1350936e294cSGirish Nandibasappa 1351936e294cSGirish Nandibasappa static void axgbe_phy_sgmii_1000_mode(struct axgbe_port *pdata) 1352936e294cSGirish Nandibasappa { 1353936e294cSGirish Nandibasappa struct axgbe_phy_data *phy_data = pdata->phy_data; 1354936e294cSGirish Nandibasappa 1355936e294cSGirish Nandibasappa axgbe_phy_set_redrv_mode(pdata); 1356936e294cSGirish Nandibasappa 1357936e294cSGirish Nandibasappa /* 1G/SGMII */ 1358cf96031aSVenkat Kumar Ande axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_SET_1G, AXGBE_MB_SUBCMD_1G_SGMII); 1359936e294cSGirish Nandibasappa 1360936e294cSGirish Nandibasappa phy_data->cur_mode = AXGBE_MODE_SGMII_1000; 1361936e294cSGirish Nandibasappa } 1362936e294cSGirish Nandibasappa 1363*1f9d2d3aSVenkat Kumar Ande static void axgbe_phy_sgmii_10_mode(struct axgbe_port *pdata) 1364*1f9d2d3aSVenkat Kumar Ande { 1365*1f9d2d3aSVenkat Kumar Ande struct axgbe_phy_data *phy_data = pdata->phy_data; 1366*1f9d2d3aSVenkat Kumar Ande 1367*1f9d2d3aSVenkat Kumar Ande axgbe_phy_set_redrv_mode(pdata); 1368*1f9d2d3aSVenkat Kumar Ande 1369*1f9d2d3aSVenkat Kumar Ande /* 10M/SGMII */ 1370*1f9d2d3aSVenkat Kumar Ande axgbe_phy_perform_ratechange(pdata, AXGBE_MB_CMD_SET_1G, AXGBE_MB_SUBCMD_10MBITS); 1371*1f9d2d3aSVenkat Kumar Ande 1372*1f9d2d3aSVenkat Kumar Ande phy_data->cur_mode = AXGBE_MODE_SGMII_10; 1373*1f9d2d3aSVenkat Kumar Ande } 1374*1f9d2d3aSVenkat Kumar Ande 1375a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_cur_mode(struct axgbe_port *pdata) 1376a5c72737SRavi Kumar { 1377a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1378a5c72737SRavi Kumar 1379a5c72737SRavi Kumar return phy_data->cur_mode; 1380a5c72737SRavi Kumar } 1381a5c72737SRavi Kumar 1382a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_switch_baset_mode(struct axgbe_port *pdata) 1383a5c72737SRavi Kumar { 1384a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1385a5c72737SRavi Kumar 1386a5c72737SRavi Kumar /* No switching if not 10GBase-T */ 1387a5c72737SRavi Kumar if (phy_data->port_mode != AXGBE_PORT_MODE_10GBASE_T) 1388a5c72737SRavi Kumar return axgbe_phy_cur_mode(pdata); 1389a5c72737SRavi Kumar 1390a5c72737SRavi Kumar switch (axgbe_phy_cur_mode(pdata)) { 1391*1f9d2d3aSVenkat Kumar Ande case AXGBE_MODE_SGMII_10: 1392a5c72737SRavi Kumar case AXGBE_MODE_SGMII_100: 1393a5c72737SRavi Kumar case AXGBE_MODE_SGMII_1000: 1394a5c72737SRavi Kumar return AXGBE_MODE_KR; 1395a5c72737SRavi Kumar case AXGBE_MODE_KR: 1396a5c72737SRavi Kumar default: 1397a5c72737SRavi Kumar return AXGBE_MODE_SGMII_1000; 1398a5c72737SRavi Kumar } 1399a5c72737SRavi Kumar } 1400a5c72737SRavi Kumar 1401a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_switch_bp_2500_mode(struct axgbe_port *pdata 1402a5c72737SRavi Kumar __rte_unused) 1403a5c72737SRavi Kumar { 1404a5c72737SRavi Kumar return AXGBE_MODE_KX_2500; 1405a5c72737SRavi Kumar } 1406a5c72737SRavi Kumar 1407a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_switch_bp_mode(struct axgbe_port *pdata) 1408a5c72737SRavi Kumar { 1409a5c72737SRavi Kumar /* If we are in KR switch to KX, and vice-versa */ 1410a5c72737SRavi Kumar switch (axgbe_phy_cur_mode(pdata)) { 1411a5c72737SRavi Kumar case AXGBE_MODE_KX_1000: 1412a5c72737SRavi Kumar return AXGBE_MODE_KR; 1413a5c72737SRavi Kumar case AXGBE_MODE_KR: 1414a5c72737SRavi Kumar default: 1415a5c72737SRavi Kumar return AXGBE_MODE_KX_1000; 1416a5c72737SRavi Kumar } 1417a5c72737SRavi Kumar } 1418a5c72737SRavi Kumar 1419a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_switch_mode(struct axgbe_port *pdata) 1420a5c72737SRavi Kumar { 1421a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1422a5c72737SRavi Kumar 1423a5c72737SRavi Kumar switch (phy_data->port_mode) { 1424a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 1425443ab5aaSSelwin Sebastian case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG: 1426a5c72737SRavi Kumar return axgbe_phy_switch_bp_mode(pdata); 1427a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 1428a5c72737SRavi Kumar return axgbe_phy_switch_bp_2500_mode(pdata); 1429a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 1430a5c72737SRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 1431a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 1432a5c72737SRavi Kumar return axgbe_phy_switch_baset_mode(pdata); 1433a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 1434a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 1435a5c72737SRavi Kumar case AXGBE_PORT_MODE_SFP: 1436a5c72737SRavi Kumar /* No switching, so just return current mode */ 1437a5c72737SRavi Kumar return axgbe_phy_cur_mode(pdata); 1438a5c72737SRavi Kumar default: 1439a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1440a5c72737SRavi Kumar } 1441a5c72737SRavi Kumar } 1442a5c72737SRavi Kumar 1443a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_basex_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_1000: 1449a5c72737SRavi Kumar return AXGBE_MODE_X; 1450a5c72737SRavi Kumar case SPEED_10000: 1451a5c72737SRavi Kumar return AXGBE_MODE_KR; 1452a5c72737SRavi Kumar default: 1453a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1454a5c72737SRavi Kumar } 1455a5c72737SRavi Kumar } 1456a5c72737SRavi Kumar 1457a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_baset_mode(struct axgbe_phy_data *phy_data 1458a5c72737SRavi Kumar __rte_unused, 1459a5c72737SRavi Kumar int speed) 1460a5c72737SRavi Kumar { 1461a5c72737SRavi Kumar switch (speed) { 1462*1f9d2d3aSVenkat Kumar Ande case SPEED_10: 1463*1f9d2d3aSVenkat Kumar Ande return AXGBE_MODE_SGMII_10; 1464a5c72737SRavi Kumar case SPEED_100: 1465a5c72737SRavi Kumar return AXGBE_MODE_SGMII_100; 1466a5c72737SRavi Kumar case SPEED_1000: 1467a5c72737SRavi Kumar return AXGBE_MODE_SGMII_1000; 1468a5c72737SRavi Kumar case SPEED_10000: 1469a5c72737SRavi Kumar return AXGBE_MODE_KR; 1470a5c72737SRavi Kumar default: 1471a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1472a5c72737SRavi Kumar } 1473a5c72737SRavi Kumar } 1474a5c72737SRavi Kumar 1475a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_sfp_mode(struct axgbe_phy_data *phy_data, 1476a5c72737SRavi Kumar int speed) 1477a5c72737SRavi Kumar { 1478a5c72737SRavi Kumar switch (speed) { 1479*1f9d2d3aSVenkat Kumar Ande case SPEED_10: 1480*1f9d2d3aSVenkat Kumar Ande return AXGBE_MODE_SGMII_10; 1481a5c72737SRavi Kumar case SPEED_100: 1482a5c72737SRavi Kumar return AXGBE_MODE_SGMII_100; 1483a5c72737SRavi Kumar case SPEED_1000: 1484a5c72737SRavi Kumar if (phy_data->sfp_base == AXGBE_SFP_BASE_1000_T) 1485a5c72737SRavi Kumar return AXGBE_MODE_SGMII_1000; 1486a5c72737SRavi Kumar else 1487a5c72737SRavi Kumar return AXGBE_MODE_X; 1488a5c72737SRavi Kumar case SPEED_10000: 1489a5c72737SRavi Kumar case SPEED_UNKNOWN: 1490a5c72737SRavi Kumar return AXGBE_MODE_SFI; 1491a5c72737SRavi Kumar default: 1492a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1493a5c72737SRavi Kumar } 1494a5c72737SRavi Kumar } 1495a5c72737SRavi Kumar 1496a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_bp_2500_mode(int speed) 1497a5c72737SRavi Kumar { 1498a5c72737SRavi Kumar switch (speed) { 1499a5c72737SRavi Kumar case SPEED_2500: 1500a5c72737SRavi Kumar return AXGBE_MODE_KX_2500; 1501a5c72737SRavi Kumar default: 1502a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1503a5c72737SRavi Kumar } 1504a5c72737SRavi Kumar } 1505a5c72737SRavi Kumar 1506a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_bp_mode(int speed) 1507a5c72737SRavi Kumar { 1508a5c72737SRavi Kumar switch (speed) { 1509a5c72737SRavi Kumar case SPEED_1000: 1510a5c72737SRavi Kumar return AXGBE_MODE_KX_1000; 1511a5c72737SRavi Kumar case SPEED_10000: 1512a5c72737SRavi Kumar return AXGBE_MODE_KR; 1513a5c72737SRavi Kumar default: 1514a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1515a5c72737SRavi Kumar } 1516a5c72737SRavi Kumar } 1517a5c72737SRavi Kumar 1518a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_mode(struct axgbe_port *pdata, 1519a5c72737SRavi Kumar int speed) 1520a5c72737SRavi Kumar { 1521a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1522a5c72737SRavi Kumar 1523a5c72737SRavi Kumar switch (phy_data->port_mode) { 1524a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 1525443ab5aaSSelwin Sebastian case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG: 1526a5c72737SRavi Kumar return axgbe_phy_get_bp_mode(speed); 1527a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 1528a5c72737SRavi Kumar return axgbe_phy_get_bp_2500_mode(speed); 1529a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 1530a5c72737SRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 1531a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 1532a5c72737SRavi Kumar return axgbe_phy_get_baset_mode(phy_data, speed); 1533a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 1534a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 1535a5c72737SRavi Kumar return axgbe_phy_get_basex_mode(phy_data, speed); 1536a5c72737SRavi Kumar case AXGBE_PORT_MODE_SFP: 1537a5c72737SRavi Kumar return axgbe_phy_get_sfp_mode(phy_data, speed); 1538a5c72737SRavi Kumar default: 1539a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1540a5c72737SRavi Kumar } 1541a5c72737SRavi Kumar } 1542a5c72737SRavi Kumar 1543a5c72737SRavi Kumar static void axgbe_phy_set_mode(struct axgbe_port *pdata, enum axgbe_mode mode) 1544a5c72737SRavi Kumar { 1545a5c72737SRavi Kumar switch (mode) { 1546a5c72737SRavi Kumar case AXGBE_MODE_KR: 1547a5c72737SRavi Kumar axgbe_phy_kr_mode(pdata); 1548a5c72737SRavi Kumar break; 1549a5c72737SRavi Kumar case AXGBE_MODE_SFI: 1550a5c72737SRavi Kumar axgbe_phy_sfi_mode(pdata); 1551a5c72737SRavi Kumar break; 1552936e294cSGirish Nandibasappa case AXGBE_MODE_KX_2500: 1553936e294cSGirish Nandibasappa axgbe_phy_kx_2500_mode(pdata); 1554936e294cSGirish Nandibasappa break; 1555936e294cSGirish Nandibasappa case AXGBE_MODE_SGMII_1000: 1556936e294cSGirish Nandibasappa axgbe_phy_sgmii_1000_mode(pdata); 1557936e294cSGirish Nandibasappa break; 1558*1f9d2d3aSVenkat Kumar Ande case AXGBE_MODE_SGMII_10: 1559*1f9d2d3aSVenkat Kumar Ande axgbe_phy_sgmii_10_mode(pdata); 1560*1f9d2d3aSVenkat Kumar Ande break; 1561a5c72737SRavi Kumar default: 1562a5c72737SRavi Kumar break; 1563a5c72737SRavi Kumar } 1564a5c72737SRavi Kumar } 1565a5c72737SRavi Kumar 1566a5c72737SRavi Kumar static bool axgbe_phy_check_mode(struct axgbe_port *pdata, 1567a5c72737SRavi Kumar enum axgbe_mode mode, u32 advert) 1568a5c72737SRavi Kumar { 1569a5c72737SRavi Kumar if (pdata->phy.autoneg == AUTONEG_ENABLE) { 1570a5c72737SRavi Kumar if (pdata->phy.advertising & advert) 1571a5c72737SRavi Kumar return true; 1572a5c72737SRavi Kumar } else { 1573a5c72737SRavi Kumar enum axgbe_mode cur_mode; 1574a5c72737SRavi Kumar 1575a5c72737SRavi Kumar cur_mode = axgbe_phy_get_mode(pdata, pdata->phy.speed); 1576a5c72737SRavi Kumar if (cur_mode == mode) 1577a5c72737SRavi Kumar return true; 1578a5c72737SRavi Kumar } 1579a5c72737SRavi Kumar 1580a5c72737SRavi Kumar return false; 1581a5c72737SRavi Kumar } 1582a5c72737SRavi Kumar 1583a5c72737SRavi Kumar static bool axgbe_phy_use_basex_mode(struct axgbe_port *pdata, 1584a5c72737SRavi Kumar enum axgbe_mode mode) 1585a5c72737SRavi Kumar { 1586a5c72737SRavi Kumar switch (mode) { 1587a5c72737SRavi Kumar case AXGBE_MODE_X: 1588a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1589a5c72737SRavi Kumar ADVERTISED_1000baseT_Full); 1590a5c72737SRavi Kumar case AXGBE_MODE_KR: 1591a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1592a5c72737SRavi Kumar ADVERTISED_10000baseT_Full); 1593a5c72737SRavi Kumar default: 1594a5c72737SRavi Kumar return false; 1595a5c72737SRavi Kumar } 1596a5c72737SRavi Kumar } 1597a5c72737SRavi Kumar 1598a5c72737SRavi Kumar static bool axgbe_phy_use_baset_mode(struct axgbe_port *pdata, 1599a5c72737SRavi Kumar enum axgbe_mode mode) 1600a5c72737SRavi Kumar { 1601a5c72737SRavi Kumar switch (mode) { 1602*1f9d2d3aSVenkat Kumar Ande case AXGBE_MODE_SGMII_10: 1603*1f9d2d3aSVenkat Kumar Ande return axgbe_phy_check_mode(pdata, mode, 1604*1f9d2d3aSVenkat Kumar Ande ADVERTISED_10baseT_Full); 1605a5c72737SRavi Kumar case AXGBE_MODE_SGMII_100: 1606a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1607a5c72737SRavi Kumar ADVERTISED_100baseT_Full); 1608a5c72737SRavi Kumar case AXGBE_MODE_SGMII_1000: 1609a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1610a5c72737SRavi Kumar ADVERTISED_1000baseT_Full); 1611a5c72737SRavi Kumar case AXGBE_MODE_KR: 1612a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1613a5c72737SRavi Kumar ADVERTISED_10000baseT_Full); 1614a5c72737SRavi Kumar default: 1615a5c72737SRavi Kumar return false; 1616a5c72737SRavi Kumar } 1617a5c72737SRavi Kumar } 1618a5c72737SRavi Kumar 1619a5c72737SRavi Kumar static bool axgbe_phy_use_sfp_mode(struct axgbe_port *pdata, 1620a5c72737SRavi Kumar enum axgbe_mode mode) 1621a5c72737SRavi Kumar { 1622a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1623a5c72737SRavi Kumar 1624a5c72737SRavi Kumar switch (mode) { 1625a5c72737SRavi Kumar case AXGBE_MODE_X: 1626a5c72737SRavi Kumar if (phy_data->sfp_base == AXGBE_SFP_BASE_1000_T) 1627a5c72737SRavi Kumar return false; 1628a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1629a5c72737SRavi Kumar ADVERTISED_1000baseT_Full); 1630*1f9d2d3aSVenkat Kumar Ande case AXGBE_MODE_SGMII_10: 1631*1f9d2d3aSVenkat Kumar Ande if (phy_data->sfp_base != AXGBE_SFP_BASE_1000_T) 1632*1f9d2d3aSVenkat Kumar Ande return false; 1633*1f9d2d3aSVenkat Kumar Ande return axgbe_phy_check_mode(pdata, mode, 1634*1f9d2d3aSVenkat Kumar Ande ADVERTISED_10baseT_Full); 1635a5c72737SRavi Kumar case AXGBE_MODE_SGMII_100: 1636a5c72737SRavi Kumar if (phy_data->sfp_base != AXGBE_SFP_BASE_1000_T) 1637a5c72737SRavi Kumar return false; 1638a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1639a5c72737SRavi Kumar ADVERTISED_100baseT_Full); 1640a5c72737SRavi Kumar case AXGBE_MODE_SGMII_1000: 1641a5c72737SRavi Kumar if (phy_data->sfp_base != AXGBE_SFP_BASE_1000_T) 1642a5c72737SRavi Kumar return false; 1643a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1644a5c72737SRavi Kumar ADVERTISED_1000baseT_Full); 1645a5c72737SRavi Kumar case AXGBE_MODE_SFI: 1646a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1647a5c72737SRavi Kumar ADVERTISED_10000baseT_Full); 1648a5c72737SRavi Kumar default: 1649a5c72737SRavi Kumar return false; 1650a5c72737SRavi Kumar } 1651a5c72737SRavi Kumar } 1652a5c72737SRavi Kumar 1653a5c72737SRavi Kumar static bool axgbe_phy_use_bp_2500_mode(struct axgbe_port *pdata, 1654a5c72737SRavi Kumar enum axgbe_mode mode) 1655a5c72737SRavi Kumar { 1656a5c72737SRavi Kumar switch (mode) { 1657a5c72737SRavi Kumar case AXGBE_MODE_KX_2500: 1658a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1659a5c72737SRavi Kumar ADVERTISED_2500baseX_Full); 1660a5c72737SRavi Kumar default: 1661a5c72737SRavi Kumar return false; 1662a5c72737SRavi Kumar } 1663a5c72737SRavi Kumar } 1664a5c72737SRavi Kumar 1665a5c72737SRavi Kumar static bool axgbe_phy_use_bp_mode(struct axgbe_port *pdata, 1666a5c72737SRavi Kumar enum axgbe_mode mode) 1667a5c72737SRavi Kumar { 1668a5c72737SRavi Kumar switch (mode) { 1669a5c72737SRavi Kumar case AXGBE_MODE_KX_1000: 1670a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1671a5c72737SRavi Kumar ADVERTISED_1000baseKX_Full); 1672a5c72737SRavi Kumar case AXGBE_MODE_KR: 1673a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1674a5c72737SRavi Kumar ADVERTISED_10000baseKR_Full); 1675a5c72737SRavi Kumar default: 1676a5c72737SRavi Kumar return false; 1677a5c72737SRavi Kumar } 1678a5c72737SRavi Kumar } 1679a5c72737SRavi Kumar 1680a5c72737SRavi Kumar static bool axgbe_phy_use_mode(struct axgbe_port *pdata, enum axgbe_mode mode) 1681a5c72737SRavi Kumar { 1682a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1683a5c72737SRavi Kumar 1684a5c72737SRavi Kumar switch (phy_data->port_mode) { 1685a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 1686443ab5aaSSelwin Sebastian case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG: 1687a5c72737SRavi Kumar return axgbe_phy_use_bp_mode(pdata, mode); 1688a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 1689a5c72737SRavi Kumar return axgbe_phy_use_bp_2500_mode(pdata, mode); 1690a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 1691a5c72737SRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 1692a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 1693a5c72737SRavi Kumar return axgbe_phy_use_baset_mode(pdata, mode); 1694a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 1695a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 1696a5c72737SRavi Kumar return axgbe_phy_use_basex_mode(pdata, mode); 1697a5c72737SRavi Kumar case AXGBE_PORT_MODE_SFP: 1698a5c72737SRavi Kumar return axgbe_phy_use_sfp_mode(pdata, mode); 1699a5c72737SRavi Kumar default: 1700a5c72737SRavi Kumar return false; 1701a5c72737SRavi Kumar } 1702a5c72737SRavi Kumar } 1703a5c72737SRavi Kumar 1704a5c72737SRavi Kumar static int axgbe_phy_link_status(struct axgbe_port *pdata, int *an_restart) 1705a5c72737SRavi Kumar { 1706a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1707a5c72737SRavi Kumar unsigned int reg; 1708a5c72737SRavi Kumar 1709a5c72737SRavi Kumar *an_restart = 0; 1710a5c72737SRavi Kumar 1711a5c72737SRavi Kumar if (phy_data->port_mode == AXGBE_PORT_MODE_SFP) { 1712a5c72737SRavi Kumar /* Check SFP signals */ 1713a5c72737SRavi Kumar axgbe_phy_sfp_detect(pdata); 1714a5c72737SRavi Kumar 1715a5c72737SRavi Kumar if (phy_data->sfp_changed) { 1716a5c72737SRavi Kumar *an_restart = 1; 1717a5c72737SRavi Kumar return 0; 1718a5c72737SRavi Kumar } 1719a5c72737SRavi Kumar 1720a5c72737SRavi Kumar if (phy_data->sfp_mod_absent || phy_data->sfp_rx_los) 1721a5c72737SRavi Kumar return 0; 1722a5c72737SRavi Kumar } 1723a5c72737SRavi Kumar 1724a5c72737SRavi Kumar /* Link status is latched low, so read once to clear 1725a5c72737SRavi Kumar * and then read again to get current state 1726a5c72737SRavi Kumar */ 1727a5c72737SRavi Kumar reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1); 1728a5c72737SRavi Kumar reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1); 1729a5c72737SRavi Kumar if (reg & MDIO_STAT1_LSTATUS) 1730a5c72737SRavi Kumar return 1; 1731a5c72737SRavi Kumar 1732edf46325SVenkat Kumar Ande if (pdata->phy.autoneg == AUTONEG_ENABLE && 1733edf46325SVenkat Kumar Ande phy_data->port_mode == AXGBE_PORT_MODE_BACKPLANE) { 1734edf46325SVenkat Kumar Ande if (rte_bit_relaxed_get32(AXGBE_LINK_INIT, &pdata->dev_state)) { 1735edf46325SVenkat Kumar Ande *an_restart = 1; 1736edf46325SVenkat Kumar Ande } 1737edf46325SVenkat Kumar Ande } 1738edf46325SVenkat Kumar Ande 1739a5c72737SRavi Kumar /* No link, attempt a receiver reset cycle */ 1740e82b0fe0SVenkat Kumar Ande if (pdata->vdata->enable_rrc && phy_data->rrc_count++) { 1741a5c72737SRavi Kumar phy_data->rrc_count = 0; 1742a5c72737SRavi Kumar axgbe_phy_rrc(pdata); 1743a5c72737SRavi Kumar } 1744a5c72737SRavi Kumar 1745a5c72737SRavi Kumar return 0; 1746a5c72737SRavi Kumar } 1747a5c72737SRavi Kumar 17484ac7516bSRavi Kumar static void axgbe_phy_sfp_gpio_setup(struct axgbe_port *pdata) 17494ac7516bSRavi Kumar { 17504ac7516bSRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 17514ac7516bSRavi Kumar 17524ac7516bSRavi Kumar phy_data->sfp_gpio_address = AXGBE_GPIO_ADDRESS_PCA9555 + 1753a3ec01b4SVenkat Kumar Ande XP_GET_BITS(pdata->pp3, XP_PROP_3, GPIO_ADDR); 17544ac7516bSRavi Kumar 1755a3ec01b4SVenkat Kumar Ande phy_data->sfp_gpio_mask = XP_GET_BITS(pdata->pp3, XP_PROP_3, GPIO_MASK); 17564ac7516bSRavi Kumar 1757a3ec01b4SVenkat Kumar Ande phy_data->sfp_gpio_rx_los = XP_GET_BITS(pdata->pp3, XP_PROP_3, 17584ac7516bSRavi Kumar GPIO_RX_LOS); 1759a3ec01b4SVenkat Kumar Ande phy_data->sfp_gpio_tx_fault = XP_GET_BITS(pdata->pp3, XP_PROP_3, 17604ac7516bSRavi Kumar GPIO_TX_FAULT); 1761a3ec01b4SVenkat Kumar Ande phy_data->sfp_gpio_mod_absent = XP_GET_BITS(pdata->pp3, XP_PROP_3, 17624ac7516bSRavi Kumar GPIO_MOD_ABS); 1763a3ec01b4SVenkat Kumar Ande phy_data->sfp_gpio_rate_select = XP_GET_BITS(pdata->pp3, XP_PROP_3, 17644ac7516bSRavi Kumar GPIO_RATE_SELECT); 17654ac7516bSRavi Kumar } 17664ac7516bSRavi Kumar 17674ac7516bSRavi Kumar static void axgbe_phy_sfp_comm_setup(struct axgbe_port *pdata) 17684ac7516bSRavi Kumar { 17694ac7516bSRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1770a3ec01b4SVenkat Kumar Ande unsigned int mux_addr_hi, mux_addr_lo; 17714ac7516bSRavi Kumar 1772a3ec01b4SVenkat Kumar Ande mux_addr_hi = XP_GET_BITS(pdata->pp4, XP_PROP_4, MUX_ADDR_HI); 1773a3ec01b4SVenkat Kumar Ande mux_addr_lo = XP_GET_BITS(pdata->pp4, XP_PROP_4, MUX_ADDR_LO); 17744ac7516bSRavi Kumar if (mux_addr_lo == AXGBE_SFP_DIRECT) 17754ac7516bSRavi Kumar return; 17764ac7516bSRavi Kumar 17774ac7516bSRavi Kumar phy_data->sfp_comm = AXGBE_SFP_COMM_PCA9545; 17784ac7516bSRavi Kumar phy_data->sfp_mux_address = (mux_addr_hi << 2) + mux_addr_lo; 1779a3ec01b4SVenkat Kumar Ande phy_data->sfp_mux_channel = XP_GET_BITS(pdata->pp4, XP_PROP_4, MUX_CHAN); 17804ac7516bSRavi Kumar } 17814ac7516bSRavi Kumar 17824ac7516bSRavi Kumar static void axgbe_phy_sfp_setup(struct axgbe_port *pdata) 17834ac7516bSRavi Kumar { 17844ac7516bSRavi Kumar axgbe_phy_sfp_comm_setup(pdata); 17854ac7516bSRavi Kumar axgbe_phy_sfp_gpio_setup(pdata); 17864ac7516bSRavi Kumar } 17874ac7516bSRavi Kumar 17884ac7516bSRavi Kumar static bool axgbe_phy_redrv_error(struct axgbe_phy_data *phy_data) 17894ac7516bSRavi Kumar { 17904ac7516bSRavi Kumar if (!phy_data->redrv) 17914ac7516bSRavi Kumar return false; 17924ac7516bSRavi Kumar 17934ac7516bSRavi Kumar if (phy_data->redrv_if >= AXGBE_PHY_REDRV_IF_MAX) 17944ac7516bSRavi Kumar return true; 17954ac7516bSRavi Kumar 17964ac7516bSRavi Kumar switch (phy_data->redrv_model) { 17974ac7516bSRavi Kumar case AXGBE_PHY_REDRV_MODEL_4223: 17984ac7516bSRavi Kumar if (phy_data->redrv_lane > 3) 17994ac7516bSRavi Kumar return true; 18004ac7516bSRavi Kumar break; 18014ac7516bSRavi Kumar case AXGBE_PHY_REDRV_MODEL_4227: 18024ac7516bSRavi Kumar if (phy_data->redrv_lane > 1) 18034ac7516bSRavi Kumar return true; 18044ac7516bSRavi Kumar break; 18054ac7516bSRavi Kumar default: 18064ac7516bSRavi Kumar return true; 18074ac7516bSRavi Kumar } 18084ac7516bSRavi Kumar 18094ac7516bSRavi Kumar return false; 18104ac7516bSRavi Kumar } 18114ac7516bSRavi Kumar 18124ac7516bSRavi Kumar static int axgbe_phy_mdio_reset_setup(struct axgbe_port *pdata) 18134ac7516bSRavi Kumar { 18144ac7516bSRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 18154ac7516bSRavi Kumar 18164ac7516bSRavi Kumar if (phy_data->conn_type != AXGBE_CONN_TYPE_MDIO) 18174ac7516bSRavi Kumar return 0; 1818a3ec01b4SVenkat Kumar Ande 1819a3ec01b4SVenkat Kumar Ande phy_data->mdio_reset = XP_GET_BITS(pdata->pp3, XP_PROP_3, MDIO_RESET); 18204ac7516bSRavi Kumar switch (phy_data->mdio_reset) { 18214ac7516bSRavi Kumar case AXGBE_MDIO_RESET_NONE: 18224ac7516bSRavi Kumar case AXGBE_MDIO_RESET_I2C_GPIO: 18234ac7516bSRavi Kumar case AXGBE_MDIO_RESET_INT_GPIO: 18244ac7516bSRavi Kumar break; 18254ac7516bSRavi Kumar default: 18264ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "unsupported MDIO reset (%#x)\n", 18274ac7516bSRavi Kumar phy_data->mdio_reset); 18284ac7516bSRavi Kumar return -EINVAL; 18294ac7516bSRavi Kumar } 18304ac7516bSRavi Kumar if (phy_data->mdio_reset == AXGBE_MDIO_RESET_I2C_GPIO) { 18314ac7516bSRavi Kumar phy_data->mdio_reset_addr = AXGBE_GPIO_ADDRESS_PCA9555 + 1832a3ec01b4SVenkat Kumar Ande XP_GET_BITS(pdata->pp3, XP_PROP_3, 18334ac7516bSRavi Kumar MDIO_RESET_I2C_ADDR); 1834a3ec01b4SVenkat Kumar Ande phy_data->mdio_reset_gpio = XP_GET_BITS(pdata->pp3, XP_PROP_3, 18354ac7516bSRavi Kumar MDIO_RESET_I2C_GPIO); 18364ac7516bSRavi Kumar } else if (phy_data->mdio_reset == AXGBE_MDIO_RESET_INT_GPIO) { 1837a3ec01b4SVenkat Kumar Ande phy_data->mdio_reset_gpio = XP_GET_BITS(pdata->pp3, XP_PROP_3, 18384ac7516bSRavi Kumar MDIO_RESET_INT_GPIO); 18394ac7516bSRavi Kumar } 18404ac7516bSRavi Kumar 18414ac7516bSRavi Kumar return 0; 18424ac7516bSRavi Kumar } 18434ac7516bSRavi Kumar 18444ac7516bSRavi Kumar static bool axgbe_phy_port_mode_mismatch(struct axgbe_port *pdata) 18454ac7516bSRavi Kumar { 18464ac7516bSRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1847*1f9d2d3aSVenkat Kumar Ande unsigned int ver; 1848*1f9d2d3aSVenkat Kumar Ande 1849*1f9d2d3aSVenkat Kumar Ande /* 10 Mbps speed is not supported in ver < 30H */ 1850*1f9d2d3aSVenkat Kumar Ande ver = AXGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER); 1851*1f9d2d3aSVenkat Kumar Ande if (ver < 0x30 && phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10) 1852*1f9d2d3aSVenkat Kumar Ande return true; 18534ac7516bSRavi Kumar 18544ac7516bSRavi Kumar switch (phy_data->port_mode) { 18554ac7516bSRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 1856443ab5aaSSelwin Sebastian case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG: 18574ac7516bSRavi Kumar if ((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 case AXGBE_PORT_MODE_BACKPLANE_2500: 18624ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500) 18634ac7516bSRavi Kumar return false; 18644ac7516bSRavi Kumar break; 18654ac7516bSRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 1866*1f9d2d3aSVenkat Kumar Ande if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10) || 1867*1f9d2d3aSVenkat Kumar Ande (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) || 18684ac7516bSRavi Kumar (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000)) 18694ac7516bSRavi Kumar return false; 18704ac7516bSRavi Kumar break; 18714ac7516bSRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 18724ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) 18734ac7516bSRavi Kumar return false; 18744ac7516bSRavi Kumar break; 18754ac7516bSRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 1876*1f9d2d3aSVenkat Kumar Ande if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10) || 1877*1f9d2d3aSVenkat Kumar Ande (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) || 18784ac7516bSRavi Kumar (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) || 18794ac7516bSRavi Kumar (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500)) 18804ac7516bSRavi Kumar return false; 18814ac7516bSRavi Kumar break; 18824ac7516bSRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 1883*1f9d2d3aSVenkat Kumar Ande if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10) || 1884*1f9d2d3aSVenkat Kumar Ande (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) || 18854ac7516bSRavi Kumar (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) || 18864ac7516bSRavi Kumar (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000)) 18874ac7516bSRavi Kumar return false; 18884ac7516bSRavi Kumar break; 18894ac7516bSRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 18904ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) 18914ac7516bSRavi Kumar return false; 18924ac7516bSRavi Kumar break; 18934ac7516bSRavi Kumar case AXGBE_PORT_MODE_SFP: 1894*1f9d2d3aSVenkat Kumar Ande if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10) || 1895*1f9d2d3aSVenkat Kumar Ande (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) || 18964ac7516bSRavi Kumar (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) || 18974ac7516bSRavi Kumar (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000)) 18984ac7516bSRavi Kumar return false; 18994ac7516bSRavi Kumar break; 19004ac7516bSRavi Kumar default: 19014ac7516bSRavi Kumar break; 19024ac7516bSRavi Kumar } 19034ac7516bSRavi Kumar 19044ac7516bSRavi Kumar return true; 19054ac7516bSRavi Kumar } 19064ac7516bSRavi Kumar 19074ac7516bSRavi Kumar static bool axgbe_phy_conn_type_mismatch(struct axgbe_port *pdata) 19084ac7516bSRavi Kumar { 19094ac7516bSRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 19104ac7516bSRavi Kumar 19114ac7516bSRavi Kumar switch (phy_data->port_mode) { 19124ac7516bSRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 1913443ab5aaSSelwin Sebastian case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG: 19144ac7516bSRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 19154ac7516bSRavi Kumar if (phy_data->conn_type == AXGBE_CONN_TYPE_BACKPLANE) 19164ac7516bSRavi Kumar return false; 19174ac7516bSRavi Kumar break; 19184ac7516bSRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 19194ac7516bSRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 19204ac7516bSRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 19214ac7516bSRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 19224ac7516bSRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 19234ac7516bSRavi Kumar if (phy_data->conn_type == AXGBE_CONN_TYPE_MDIO) 19244ac7516bSRavi Kumar return false; 19254ac7516bSRavi Kumar break; 19264ac7516bSRavi Kumar case AXGBE_PORT_MODE_SFP: 19274ac7516bSRavi Kumar if (phy_data->conn_type == AXGBE_CONN_TYPE_SFP) 19284ac7516bSRavi Kumar return false; 19294ac7516bSRavi Kumar break; 19304ac7516bSRavi Kumar default: 19314ac7516bSRavi Kumar break; 19324ac7516bSRavi Kumar } 19334ac7516bSRavi Kumar 19344ac7516bSRavi Kumar return true; 19354ac7516bSRavi Kumar } 19364ac7516bSRavi Kumar 19374ac7516bSRavi Kumar static bool axgbe_phy_port_enabled(struct axgbe_port *pdata) 19384ac7516bSRavi Kumar { 1939a3ec01b4SVenkat Kumar Ande if (!XP_GET_BITS(pdata->pp0, XP_PROP_0, PORT_SPEEDS)) 19404ac7516bSRavi Kumar return false; 1941a3ec01b4SVenkat Kumar Ande if (!XP_GET_BITS(pdata->pp0, XP_PROP_0, CONN_TYPE)) 19424ac7516bSRavi Kumar return false; 19434ac7516bSRavi Kumar 19444ac7516bSRavi Kumar return true; 19454ac7516bSRavi Kumar } 19464ac7516bSRavi Kumar 194700072056SRavi Kumar static void axgbe_phy_cdr_track(struct axgbe_port *pdata) 194800072056SRavi Kumar { 194900072056SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 195000072056SRavi Kumar 195100072056SRavi Kumar if (!pdata->vdata->an_cdr_workaround) 195200072056SRavi Kumar return; 195300072056SRavi Kumar 195400072056SRavi Kumar if (!phy_data->phy_cdr_notrack) 195500072056SRavi Kumar return; 195600072056SRavi Kumar 195700072056SRavi Kumar rte_delay_us(phy_data->phy_cdr_delay + 400); 195800072056SRavi Kumar 195900072056SRavi Kumar XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_CDR_CONTROL, 196000072056SRavi Kumar AXGBE_PMA_CDR_TRACK_EN_MASK, 196100072056SRavi Kumar AXGBE_PMA_CDR_TRACK_EN_ON); 196200072056SRavi Kumar 196300072056SRavi Kumar phy_data->phy_cdr_notrack = 0; 196400072056SRavi Kumar } 196500072056SRavi Kumar 196600072056SRavi Kumar static void axgbe_phy_cdr_notrack(struct axgbe_port *pdata) 196700072056SRavi Kumar { 196800072056SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 196900072056SRavi Kumar 197000072056SRavi Kumar if (!pdata->vdata->an_cdr_workaround) 197100072056SRavi Kumar return; 197200072056SRavi Kumar 197300072056SRavi Kumar if (phy_data->phy_cdr_notrack) 197400072056SRavi Kumar return; 197500072056SRavi Kumar 197600072056SRavi Kumar XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_CDR_CONTROL, 197700072056SRavi Kumar AXGBE_PMA_CDR_TRACK_EN_MASK, 197800072056SRavi Kumar AXGBE_PMA_CDR_TRACK_EN_OFF); 197900072056SRavi Kumar 198000072056SRavi Kumar axgbe_phy_rrc(pdata); 198100072056SRavi Kumar 198200072056SRavi Kumar phy_data->phy_cdr_notrack = 1; 198300072056SRavi Kumar } 198400072056SRavi Kumar 198500072056SRavi Kumar static void axgbe_phy_kr_training_post(struct axgbe_port *pdata) 198600072056SRavi Kumar { 198700072056SRavi Kumar if (!pdata->cdr_track_early) 198800072056SRavi Kumar axgbe_phy_cdr_track(pdata); 198900072056SRavi Kumar } 199000072056SRavi Kumar 199100072056SRavi Kumar static void axgbe_phy_kr_training_pre(struct axgbe_port *pdata) 199200072056SRavi Kumar { 199300072056SRavi Kumar if (pdata->cdr_track_early) 199400072056SRavi Kumar axgbe_phy_cdr_track(pdata); 199500072056SRavi Kumar } 199600072056SRavi Kumar 199700072056SRavi Kumar static void axgbe_phy_an_post(struct axgbe_port *pdata) 199800072056SRavi Kumar { 199900072056SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 200000072056SRavi Kumar 200100072056SRavi Kumar switch (pdata->an_mode) { 200200072056SRavi Kumar case AXGBE_AN_MODE_CL73: 200300072056SRavi Kumar case AXGBE_AN_MODE_CL73_REDRV: 200400072056SRavi Kumar if (phy_data->cur_mode != AXGBE_MODE_KR) 200500072056SRavi Kumar break; 200600072056SRavi Kumar 200700072056SRavi Kumar axgbe_phy_cdr_track(pdata); 200800072056SRavi Kumar 200900072056SRavi Kumar switch (pdata->an_result) { 201000072056SRavi Kumar case AXGBE_AN_READY: 201100072056SRavi Kumar case AXGBE_AN_COMPLETE: 201200072056SRavi Kumar break; 201300072056SRavi Kumar default: 201400072056SRavi Kumar if (phy_data->phy_cdr_delay < AXGBE_CDR_DELAY_MAX) 201500072056SRavi Kumar phy_data->phy_cdr_delay += AXGBE_CDR_DELAY_INC; 201600072056SRavi Kumar break; 201700072056SRavi Kumar } 201800072056SRavi Kumar break; 201900072056SRavi Kumar default: 202000072056SRavi Kumar break; 202100072056SRavi Kumar } 202200072056SRavi Kumar } 202300072056SRavi Kumar 202400072056SRavi Kumar static void axgbe_phy_an_pre(struct axgbe_port *pdata) 202500072056SRavi Kumar { 202600072056SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 202700072056SRavi Kumar 202800072056SRavi Kumar switch (pdata->an_mode) { 202900072056SRavi Kumar case AXGBE_AN_MODE_CL73: 203000072056SRavi Kumar case AXGBE_AN_MODE_CL73_REDRV: 203100072056SRavi Kumar if (phy_data->cur_mode != AXGBE_MODE_KR) 203200072056SRavi Kumar break; 203300072056SRavi Kumar 203400072056SRavi Kumar axgbe_phy_cdr_notrack(pdata); 203500072056SRavi Kumar break; 203600072056SRavi Kumar default: 203700072056SRavi Kumar break; 203800072056SRavi Kumar } 203900072056SRavi Kumar } 204000072056SRavi Kumar 2041a5c72737SRavi Kumar static void axgbe_phy_stop(struct axgbe_port *pdata) 2042a5c72737SRavi Kumar { 2043a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 2044a5c72737SRavi Kumar 2045a5c72737SRavi Kumar /* Reset SFP data */ 2046a5c72737SRavi Kumar axgbe_phy_sfp_reset(phy_data); 2047a5c72737SRavi Kumar axgbe_phy_sfp_mod_absent(pdata); 2048a5c72737SRavi Kumar 204900072056SRavi Kumar /* Reset CDR support */ 205000072056SRavi Kumar axgbe_phy_cdr_track(pdata); 205100072056SRavi Kumar 2052a5c72737SRavi Kumar /* Power off the PHY */ 2053a5c72737SRavi Kumar axgbe_phy_power_off(pdata); 2054a5c72737SRavi Kumar 2055a5c72737SRavi Kumar /* Stop the I2C controller */ 2056a5c72737SRavi Kumar pdata->i2c_if.i2c_stop(pdata); 2057a5c72737SRavi Kumar } 2058a5c72737SRavi Kumar 2059a5c72737SRavi Kumar static int axgbe_phy_start(struct axgbe_port *pdata) 2060a5c72737SRavi Kumar { 2061a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 2062a5c72737SRavi Kumar int ret; 2063a5c72737SRavi Kumar 2064a5c72737SRavi Kumar /* Start the I2C controller */ 2065a5c72737SRavi Kumar ret = pdata->i2c_if.i2c_start(pdata); 2066a5c72737SRavi Kumar if (ret) 2067a5c72737SRavi Kumar return ret; 2068a5c72737SRavi Kumar 2069a5c72737SRavi Kumar /* Start in highest supported mode */ 2070a5c72737SRavi Kumar axgbe_phy_set_mode(pdata, phy_data->start_mode); 2071a5c72737SRavi Kumar 207200072056SRavi Kumar /* Reset CDR support */ 207300072056SRavi Kumar axgbe_phy_cdr_track(pdata); 207400072056SRavi Kumar 2075a5c72737SRavi Kumar /* After starting the I2C controller, we can check for an SFP */ 2076a5c72737SRavi Kumar switch (phy_data->port_mode) { 2077a5c72737SRavi Kumar case AXGBE_PORT_MODE_SFP: 2078a5c72737SRavi Kumar axgbe_phy_sfp_detect(pdata); 2079a5c72737SRavi Kumar break; 2080a5c72737SRavi Kumar default: 2081a5c72737SRavi Kumar break; 2082a5c72737SRavi Kumar } 2083102b6ec3SGirish Nandibasappa pdata->phy.advertising &= axgbe_phy_an_advertising(pdata); 2084a5c72737SRavi Kumar 2085a5c72737SRavi Kumar return ret; 2086a5c72737SRavi Kumar } 2087a5c72737SRavi Kumar 2088a5c72737SRavi Kumar static int axgbe_phy_reset(struct axgbe_port *pdata) 2089a5c72737SRavi Kumar { 2090a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 2091a5c72737SRavi Kumar enum axgbe_mode cur_mode; 2092a5c72737SRavi Kumar 2093a5c72737SRavi Kumar /* Reset by power cycling the PHY */ 2094a5c72737SRavi Kumar cur_mode = phy_data->cur_mode; 2095a5c72737SRavi Kumar axgbe_phy_power_off(pdata); 2096a5c72737SRavi Kumar /* First time reset is done with passed unknown mode*/ 2097a5c72737SRavi Kumar axgbe_phy_set_mode(pdata, cur_mode); 2098a5c72737SRavi Kumar return 0; 2099a5c72737SRavi Kumar } 2100a5c72737SRavi Kumar 21014ac7516bSRavi Kumar static int axgbe_phy_init(struct axgbe_port *pdata) 21024ac7516bSRavi Kumar { 21034ac7516bSRavi Kumar struct axgbe_phy_data *phy_data; 21044ac7516bSRavi Kumar int ret; 21054ac7516bSRavi Kumar 21064ac7516bSRavi Kumar /* Check if enabled */ 21074ac7516bSRavi Kumar if (!axgbe_phy_port_enabled(pdata)) { 21084ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "device is not enabled\n"); 21094ac7516bSRavi Kumar return -ENODEV; 21104ac7516bSRavi Kumar } 21114ac7516bSRavi Kumar 21124ac7516bSRavi Kumar /* Initialize the I2C controller */ 21134ac7516bSRavi Kumar ret = pdata->i2c_if.i2c_init(pdata); 21144ac7516bSRavi Kumar if (ret) 21154ac7516bSRavi Kumar return ret; 21164ac7516bSRavi Kumar 21174ac7516bSRavi Kumar phy_data = rte_zmalloc("phy_data memory", sizeof(*phy_data), 0); 21184ac7516bSRavi Kumar if (!phy_data) { 21194ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "phy_data allocation failed\n"); 21204ac7516bSRavi Kumar return -ENOMEM; 21214ac7516bSRavi Kumar } 21224ac7516bSRavi Kumar pdata->phy_data = phy_data; 21234ac7516bSRavi Kumar 2124a3ec01b4SVenkat Kumar Ande phy_data->port_mode = XP_GET_BITS(pdata->pp0, XP_PROP_0, PORT_MODE); 2125a3ec01b4SVenkat Kumar Ande phy_data->port_id = XP_GET_BITS(pdata->pp0, XP_PROP_0, PORT_ID); 2126a3ec01b4SVenkat Kumar Ande phy_data->port_speeds = XP_GET_BITS(pdata->pp0, XP_PROP_0, PORT_SPEEDS); 2127a3ec01b4SVenkat Kumar Ande phy_data->conn_type = XP_GET_BITS(pdata->pp0, XP_PROP_0, CONN_TYPE); 2128a3ec01b4SVenkat Kumar Ande phy_data->mdio_addr = XP_GET_BITS(pdata->pp0, XP_PROP_0, MDIO_ADDR); 21294ac7516bSRavi Kumar 2130a3ec01b4SVenkat Kumar Ande phy_data->redrv = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_PRESENT); 2131a3ec01b4SVenkat Kumar Ande phy_data->redrv_if = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_IF); 2132a3ec01b4SVenkat Kumar Ande phy_data->redrv_addr = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_ADDR); 2133a3ec01b4SVenkat Kumar Ande phy_data->redrv_lane = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_LANE); 2134a3ec01b4SVenkat Kumar Ande phy_data->redrv_model = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_MODEL); 21354ac7516bSRavi Kumar 21364ac7516bSRavi Kumar /* Validate the connection requested */ 21374ac7516bSRavi Kumar if (axgbe_phy_conn_type_mismatch(pdata)) { 21384ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "phy mode/connection mismatch (%#x/%#x)\n", 21394ac7516bSRavi Kumar phy_data->port_mode, phy_data->conn_type); 21404ac7516bSRavi Kumar return -EINVAL; 21414ac7516bSRavi Kumar } 21424ac7516bSRavi Kumar 21434ac7516bSRavi Kumar /* Validate the mode requested */ 21444ac7516bSRavi Kumar if (axgbe_phy_port_mode_mismatch(pdata)) { 21454ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "phy mode/speed mismatch (%#x/%#x)\n", 21464ac7516bSRavi Kumar phy_data->port_mode, phy_data->port_speeds); 21474ac7516bSRavi Kumar return -EINVAL; 21484ac7516bSRavi Kumar } 21494ac7516bSRavi Kumar 21504ac7516bSRavi Kumar /* Check for and validate MDIO reset support */ 21514ac7516bSRavi Kumar ret = axgbe_phy_mdio_reset_setup(pdata); 21524ac7516bSRavi Kumar if (ret) 21534ac7516bSRavi Kumar return ret; 21544ac7516bSRavi Kumar 21554ac7516bSRavi Kumar /* Validate the re-driver information */ 21564ac7516bSRavi Kumar if (axgbe_phy_redrv_error(phy_data)) { 21574ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "phy re-driver settings error\n"); 21584ac7516bSRavi Kumar return -EINVAL; 21594ac7516bSRavi Kumar } 21604ac7516bSRavi Kumar pdata->kr_redrv = phy_data->redrv; 21614ac7516bSRavi Kumar 21624ac7516bSRavi Kumar /* Indicate current mode is unknown */ 21634ac7516bSRavi Kumar phy_data->cur_mode = AXGBE_MODE_UNKNOWN; 21644ac7516bSRavi Kumar 21654ac7516bSRavi Kumar /* Initialize supported features */ 21664ac7516bSRavi Kumar pdata->phy.supported = 0; 21674ac7516bSRavi Kumar 21684ac7516bSRavi Kumar switch (phy_data->port_mode) { 21694ac7516bSRavi Kumar /* Backplane support */ 21704ac7516bSRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 21714ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Autoneg; 2172443ab5aaSSelwin Sebastian /* Fallthrough */ 2173443ab5aaSSelwin Sebastian case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG: 21744ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 21754ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Backplane; 21764ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { 21774ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_1000baseKX_Full; 21784ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_KX_1000; 21794ac7516bSRavi Kumar } 21804ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) { 21814ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_10000baseKR_Full; 21824ac7516bSRavi Kumar if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) 21834ac7516bSRavi Kumar pdata->phy.supported |= 21844ac7516bSRavi Kumar SUPPORTED_10000baseR_FEC; 21854ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_KR; 21864ac7516bSRavi Kumar } 21874ac7516bSRavi Kumar 21884ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE; 21894ac7516bSRavi Kumar break; 21904ac7516bSRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 21914ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 21924ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Backplane; 21934ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_2500baseX_Full; 21944ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_KX_2500; 21954ac7516bSRavi Kumar 21964ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE; 21974ac7516bSRavi Kumar break; 21984ac7516bSRavi Kumar 21994ac7516bSRavi Kumar /* MDIO 1GBase-T support */ 22004ac7516bSRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 22014ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Autoneg; 22024ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 22034ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_TP; 2204*1f9d2d3aSVenkat Kumar Ande if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10) { 2205*1f9d2d3aSVenkat Kumar Ande pdata->phy.supported |= SUPPORTED_10baseT_Full; 2206*1f9d2d3aSVenkat Kumar Ande phy_data->start_mode = AXGBE_MODE_SGMII_10; 2207*1f9d2d3aSVenkat Kumar Ande } 22084ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) { 22094ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_100baseT_Full; 22104ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_100; 22114ac7516bSRavi Kumar } 22124ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { 22134ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_1000baseT_Full; 22144ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_1000; 22154ac7516bSRavi Kumar } 22164ac7516bSRavi Kumar 22174ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_CL22; 22184ac7516bSRavi Kumar break; 22194ac7516bSRavi Kumar 22204ac7516bSRavi Kumar /* MDIO Base-X support */ 22214ac7516bSRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 22224ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Autoneg; 22234ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 22244ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_FIBRE; 22254ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_1000baseT_Full; 22264ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_X; 22274ac7516bSRavi Kumar 22284ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_CL22; 22294ac7516bSRavi Kumar break; 22304ac7516bSRavi Kumar 22314ac7516bSRavi Kumar /* MDIO NBase-T support */ 22324ac7516bSRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 22334ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Autoneg; 22344ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 22354ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_TP; 2236*1f9d2d3aSVenkat Kumar Ande if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10) { 2237*1f9d2d3aSVenkat Kumar Ande pdata->phy.supported |= SUPPORTED_10baseT_Full; 2238*1f9d2d3aSVenkat Kumar Ande phy_data->start_mode = AXGBE_MODE_SGMII_10; 2239*1f9d2d3aSVenkat Kumar Ande } 22404ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) { 22414ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_100baseT_Full; 22424ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_100; 22434ac7516bSRavi Kumar } 22444ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { 22454ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_1000baseT_Full; 22464ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_1000; 22474ac7516bSRavi Kumar } 22484ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500) { 22494ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_2500baseX_Full; 22504ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_KX_2500; 22514ac7516bSRavi Kumar } 22524ac7516bSRavi Kumar 22534ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_CL45; 22544ac7516bSRavi Kumar break; 22554ac7516bSRavi Kumar 22564ac7516bSRavi Kumar /* 10GBase-T support */ 22574ac7516bSRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 22584ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Autoneg; 22594ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 22604ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_TP; 2261*1f9d2d3aSVenkat Kumar Ande if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10) { 2262*1f9d2d3aSVenkat Kumar Ande pdata->phy.supported |= SUPPORTED_10baseT_Full; 2263*1f9d2d3aSVenkat Kumar Ande phy_data->start_mode = AXGBE_MODE_SGMII_10; 2264*1f9d2d3aSVenkat Kumar Ande } 22654ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) { 22664ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_100baseT_Full; 22674ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_100; 22684ac7516bSRavi Kumar } 22694ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { 22704ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_1000baseT_Full; 22714ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_1000; 22724ac7516bSRavi Kumar } 22734ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) { 22744ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_10000baseT_Full; 22754ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_KR; 22764ac7516bSRavi Kumar } 22774ac7516bSRavi Kumar 22784ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE; 22794ac7516bSRavi Kumar break; 22804ac7516bSRavi Kumar 22814ac7516bSRavi Kumar /* 10GBase-R support */ 22824ac7516bSRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 22834ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Autoneg; 22844ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 22854ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_TP; 22864ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_10000baseT_Full; 22874ac7516bSRavi Kumar if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) 22884ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_10000baseR_FEC; 22894ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SFI; 22904ac7516bSRavi Kumar 22914ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE; 22924ac7516bSRavi Kumar break; 22934ac7516bSRavi Kumar 22944ac7516bSRavi Kumar /* SFP support */ 22954ac7516bSRavi Kumar case AXGBE_PORT_MODE_SFP: 22964ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Autoneg; 22974ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 22984ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_TP; 22994ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_FIBRE; 2300*1f9d2d3aSVenkat Kumar Ande if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10) { 2301*1f9d2d3aSVenkat Kumar Ande pdata->phy.supported |= SUPPORTED_10baseT_Full; 2302*1f9d2d3aSVenkat Kumar Ande phy_data->start_mode = AXGBE_MODE_SGMII_10; 2303*1f9d2d3aSVenkat Kumar Ande } 23044ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) { 23054ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_100baseT_Full; 23064ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_100; 23074ac7516bSRavi Kumar } 23084ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { 23094ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_1000baseT_Full; 23104ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_1000; 23114ac7516bSRavi Kumar } 23124ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) { 23134ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_10000baseT_Full; 23144ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SFI; 23154ac7516bSRavi Kumar if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) 23164ac7516bSRavi Kumar pdata->phy.supported |= 23174ac7516bSRavi Kumar SUPPORTED_10000baseR_FEC; 23184ac7516bSRavi Kumar } 23194ac7516bSRavi Kumar 23204ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_CL22; 23214ac7516bSRavi Kumar 23224ac7516bSRavi Kumar axgbe_phy_sfp_setup(pdata); 23234ac7516bSRavi Kumar break; 23244ac7516bSRavi Kumar default: 23254ac7516bSRavi Kumar return -EINVAL; 23264ac7516bSRavi Kumar } 23274ac7516bSRavi Kumar 23284ac7516bSRavi Kumar if ((phy_data->conn_type & AXGBE_CONN_TYPE_MDIO) && 23294ac7516bSRavi Kumar (phy_data->phydev_mode != AXGBE_MDIO_MODE_NONE)) { 23304ac7516bSRavi Kumar ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->mdio_addr, 23314ac7516bSRavi Kumar phy_data->phydev_mode); 23324ac7516bSRavi Kumar if (ret) { 23334ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "mdio port/clause not compatible (%d/%u)\n", 23344ac7516bSRavi Kumar phy_data->mdio_addr, phy_data->phydev_mode); 23354ac7516bSRavi Kumar return -EINVAL; 23364ac7516bSRavi Kumar } 23374ac7516bSRavi Kumar } 23384ac7516bSRavi Kumar 23394ac7516bSRavi Kumar if (phy_data->redrv && !phy_data->redrv_if) { 23404ac7516bSRavi Kumar ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->redrv_addr, 23414ac7516bSRavi Kumar AXGBE_MDIO_MODE_CL22); 23424ac7516bSRavi Kumar if (ret) { 23434ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "redriver mdio port not compatible (%u)\n", 23444ac7516bSRavi Kumar phy_data->redrv_addr); 23454ac7516bSRavi Kumar return -EINVAL; 23464ac7516bSRavi Kumar } 23474ac7516bSRavi Kumar } 234800072056SRavi Kumar 234900072056SRavi Kumar phy_data->phy_cdr_delay = AXGBE_CDR_DELAY_INIT; 23504ac7516bSRavi Kumar return 0; 23514ac7516bSRavi Kumar } 23524ac7516bSRavi Kumar void axgbe_init_function_ptrs_phy_v2(struct axgbe_phy_if *phy_if) 23534ac7516bSRavi Kumar { 23544ac7516bSRavi Kumar struct axgbe_phy_impl_if *phy_impl = &phy_if->phy_impl; 23554ac7516bSRavi Kumar 23564ac7516bSRavi Kumar phy_impl->init = axgbe_phy_init; 2357a5c72737SRavi Kumar phy_impl->reset = axgbe_phy_reset; 2358a5c72737SRavi Kumar phy_impl->start = axgbe_phy_start; 2359a5c72737SRavi Kumar phy_impl->stop = axgbe_phy_stop; 2360a5c72737SRavi Kumar phy_impl->link_status = axgbe_phy_link_status; 2361a5c72737SRavi Kumar phy_impl->use_mode = axgbe_phy_use_mode; 2362a5c72737SRavi Kumar phy_impl->set_mode = axgbe_phy_set_mode; 2363a5c72737SRavi Kumar phy_impl->get_mode = axgbe_phy_get_mode; 2364a5c72737SRavi Kumar phy_impl->switch_mode = axgbe_phy_switch_mode; 2365a5c72737SRavi Kumar phy_impl->cur_mode = axgbe_phy_cur_mode; 2366a5c72737SRavi Kumar phy_impl->an_mode = axgbe_phy_an_mode; 2367a5c72737SRavi Kumar phy_impl->an_config = axgbe_phy_an_config; 2368a5c72737SRavi Kumar phy_impl->an_advertising = axgbe_phy_an_advertising; 2369a5c72737SRavi Kumar phy_impl->an_outcome = axgbe_phy_an_outcome; 237000072056SRavi Kumar 237100072056SRavi Kumar phy_impl->an_pre = axgbe_phy_an_pre; 237200072056SRavi Kumar phy_impl->an_post = axgbe_phy_an_post; 237300072056SRavi Kumar 237400072056SRavi Kumar phy_impl->kr_training_pre = axgbe_phy_kr_training_pre; 237500072056SRavi Kumar phy_impl->kr_training_post = axgbe_phy_kr_training_post; 23764ac7516bSRavi Kumar } 2377