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