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