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 581a5c72737SRavi Kumar if (!memcmp(&sfp_eeprom->base[AXGBE_SFP_BASE_VENDOR_PN], 58227578231SAndy Green AXGBE_BEL_FUSE_PARTNO, strlen(AXGBE_BEL_FUSE_PARTNO))) { 583a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_1000_SX; 584a5c72737SRavi Kumar phy_data->sfp_cable = AXGBE_SFP_CABLE_ACTIVE; 585a5c72737SRavi Kumar phy_data->sfp_speed = AXGBE_SFP_SPEED_1000; 586a5c72737SRavi Kumar return true; 587a5c72737SRavi Kumar } 588a5c72737SRavi Kumar 589a5c72737SRavi Kumar return false; 590a5c72737SRavi Kumar } 591a5c72737SRavi Kumar 592a5c72737SRavi Kumar static bool axgbe_phy_sfp_parse_quirks(struct axgbe_port *pdata) 593a5c72737SRavi Kumar { 594a5c72737SRavi Kumar if (axgbe_phy_belfuse_parse_quirks(pdata)) 595a5c72737SRavi Kumar return true; 596a5c72737SRavi Kumar 597a5c72737SRavi Kumar return false; 598a5c72737SRavi Kumar } 599a5c72737SRavi Kumar 600a5c72737SRavi Kumar static void axgbe_phy_sfp_parse_eeprom(struct axgbe_port *pdata) 601a5c72737SRavi Kumar { 602a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 603a5c72737SRavi Kumar struct axgbe_sfp_eeprom *sfp_eeprom = &phy_data->sfp_eeprom; 604a5c72737SRavi Kumar uint8_t *sfp_base; 605a5c72737SRavi Kumar 606a5c72737SRavi Kumar sfp_base = sfp_eeprom->base; 607a5c72737SRavi Kumar 608a5c72737SRavi Kumar if (sfp_base[AXGBE_SFP_BASE_ID] != AXGBE_SFP_ID_SFP) 609a5c72737SRavi Kumar return; 610a5c72737SRavi Kumar 611a5c72737SRavi Kumar if (sfp_base[AXGBE_SFP_BASE_EXT_ID] != AXGBE_SFP_EXT_ID_SFP) 612a5c72737SRavi Kumar return; 613a5c72737SRavi Kumar 614936e294cSGirish Nandibasappa axgbe_phy_sfp_parse_quirks(pdata); 615a5c72737SRavi Kumar 616a5c72737SRavi Kumar /* Assume ACTIVE cable unless told it is PASSIVE */ 617a5c72737SRavi Kumar if (sfp_base[AXGBE_SFP_BASE_CABLE] & AXGBE_SFP_BASE_CABLE_PASSIVE) { 618a5c72737SRavi Kumar phy_data->sfp_cable = AXGBE_SFP_CABLE_PASSIVE; 619a5c72737SRavi Kumar phy_data->sfp_cable_len = sfp_base[AXGBE_SFP_BASE_CU_CABLE_LEN]; 620a5c72737SRavi Kumar } else { 621a5c72737SRavi Kumar phy_data->sfp_cable = AXGBE_SFP_CABLE_ACTIVE; 622a5c72737SRavi Kumar } 623a5c72737SRavi Kumar 624a5c72737SRavi Kumar /* Determine the type of SFP */ 625a5c72737SRavi Kumar if (sfp_base[AXGBE_SFP_BASE_10GBE_CC] & AXGBE_SFP_BASE_10GBE_CC_SR) 626a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_10000_SR; 627a5c72737SRavi Kumar else if (sfp_base[AXGBE_SFP_BASE_10GBE_CC] & AXGBE_SFP_BASE_10GBE_CC_LR) 628a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_10000_LR; 629a5c72737SRavi Kumar else if (sfp_base[AXGBE_SFP_BASE_10GBE_CC] & 630a5c72737SRavi Kumar AXGBE_SFP_BASE_10GBE_CC_LRM) 631a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_10000_LRM; 632a5c72737SRavi Kumar else if (sfp_base[AXGBE_SFP_BASE_10GBE_CC] & AXGBE_SFP_BASE_10GBE_CC_ER) 633a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_10000_ER; 634a5c72737SRavi Kumar else if (sfp_base[AXGBE_SFP_BASE_1GBE_CC] & AXGBE_SFP_BASE_1GBE_CC_SX) 635a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_1000_SX; 636a5c72737SRavi Kumar else if (sfp_base[AXGBE_SFP_BASE_1GBE_CC] & AXGBE_SFP_BASE_1GBE_CC_LX) 637a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_1000_LX; 638a5c72737SRavi Kumar else if (sfp_base[AXGBE_SFP_BASE_1GBE_CC] & AXGBE_SFP_BASE_1GBE_CC_CX) 639a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_1000_CX; 640a5c72737SRavi Kumar else if (sfp_base[AXGBE_SFP_BASE_1GBE_CC] & AXGBE_SFP_BASE_1GBE_CC_T) 641a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_1000_T; 642a5c72737SRavi Kumar else if ((phy_data->sfp_cable == AXGBE_SFP_CABLE_PASSIVE) && 643a5c72737SRavi Kumar axgbe_phy_sfp_bit_rate(sfp_eeprom, AXGBE_SFP_SPEED_10000)) 644a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_10000_CR; 645a5c72737SRavi Kumar 646a5c72737SRavi Kumar switch (phy_data->sfp_base) { 647a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_T: 648a5c72737SRavi Kumar phy_data->sfp_speed = AXGBE_SFP_SPEED_100_1000; 649a5c72737SRavi Kumar break; 650a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_SX: 651a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_LX: 652a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_CX: 653a5c72737SRavi Kumar phy_data->sfp_speed = AXGBE_SFP_SPEED_1000; 654a5c72737SRavi Kumar break; 655a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_SR: 656a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_LR: 657a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_LRM: 658a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_ER: 659a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_CR: 660a5c72737SRavi Kumar phy_data->sfp_speed = AXGBE_SFP_SPEED_10000; 661a5c72737SRavi Kumar break; 662a5c72737SRavi Kumar default: 663a5c72737SRavi Kumar break; 664a5c72737SRavi Kumar } 665a5c72737SRavi Kumar } 666a5c72737SRavi Kumar 667a5c72737SRavi Kumar static bool axgbe_phy_sfp_verify_eeprom(uint8_t cc_in, uint8_t *buf, 668a5c72737SRavi Kumar unsigned int len) 669a5c72737SRavi Kumar { 670a5c72737SRavi Kumar uint8_t cc; 671a5c72737SRavi Kumar 672a5c72737SRavi Kumar for (cc = 0; len; buf++, len--) 673a5c72737SRavi Kumar cc += *buf; 674a5c72737SRavi Kumar 675a5c72737SRavi Kumar return (cc == cc_in) ? true : false; 676a5c72737SRavi Kumar } 677a5c72737SRavi Kumar 678a5c72737SRavi Kumar static int axgbe_phy_sfp_read_eeprom(struct axgbe_port *pdata) 679a5c72737SRavi Kumar { 680a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 681a5c72737SRavi Kumar struct axgbe_sfp_eeprom sfp_eeprom; 682a5c72737SRavi Kumar uint8_t eeprom_addr; 683a5c72737SRavi Kumar int ret; 684a5c72737SRavi Kumar 685a5c72737SRavi Kumar ret = axgbe_phy_sfp_get_mux(pdata); 686a5c72737SRavi Kumar if (ret) { 687a5c72737SRavi Kumar PMD_DRV_LOG(ERR, "I2C error setting SFP MUX\n"); 688a5c72737SRavi Kumar return ret; 689a5c72737SRavi Kumar } 690a5c72737SRavi Kumar 691a5c72737SRavi Kumar /* Read the SFP serial ID eeprom */ 692a5c72737SRavi Kumar eeprom_addr = 0; 693a5c72737SRavi Kumar ret = axgbe_phy_i2c_read(pdata, AXGBE_SFP_SERIAL_ID_ADDRESS, 694a5c72737SRavi Kumar &eeprom_addr, sizeof(eeprom_addr), 695a5c72737SRavi Kumar &sfp_eeprom, sizeof(sfp_eeprom)); 696a5c72737SRavi Kumar if (ret) { 697a5c72737SRavi Kumar PMD_DRV_LOG(ERR, "I2C error reading SFP EEPROM\n"); 698a5c72737SRavi Kumar goto put; 699a5c72737SRavi Kumar } 700a5c72737SRavi Kumar 701a5c72737SRavi Kumar /* Validate the contents read */ 702a5c72737SRavi Kumar if (!axgbe_phy_sfp_verify_eeprom(sfp_eeprom.base[AXGBE_SFP_BASE_CC], 703a5c72737SRavi Kumar sfp_eeprom.base, 704a5c72737SRavi Kumar sizeof(sfp_eeprom.base) - 1)) { 705a5c72737SRavi Kumar ret = -EINVAL; 706a5c72737SRavi Kumar goto put; 707a5c72737SRavi Kumar } 708a5c72737SRavi Kumar 709a5c72737SRavi Kumar if (!axgbe_phy_sfp_verify_eeprom(sfp_eeprom.extd[AXGBE_SFP_EXTD_CC], 710a5c72737SRavi Kumar sfp_eeprom.extd, 711a5c72737SRavi Kumar sizeof(sfp_eeprom.extd) - 1)) { 712a5c72737SRavi Kumar ret = -EINVAL; 713a5c72737SRavi Kumar goto put; 714a5c72737SRavi Kumar } 715a5c72737SRavi Kumar 716a5c72737SRavi Kumar /* Check for an added or changed SFP */ 717a5c72737SRavi Kumar if (memcmp(&phy_data->sfp_eeprom, &sfp_eeprom, sizeof(sfp_eeprom))) { 718a5c72737SRavi Kumar phy_data->sfp_changed = 1; 719a5c72737SRavi Kumar memcpy(&phy_data->sfp_eeprom, &sfp_eeprom, sizeof(sfp_eeprom)); 720a5c72737SRavi Kumar 721a5c72737SRavi Kumar if (sfp_eeprom.extd[AXGBE_SFP_EXTD_SFF_8472]) { 722a5c72737SRavi Kumar uint8_t diag_type; 723a5c72737SRavi Kumar diag_type = sfp_eeprom.extd[AXGBE_SFP_EXTD_DIAG]; 724a5c72737SRavi Kumar 725a5c72737SRavi Kumar if (!(diag_type & AXGBE_SFP_EXTD_DIAG_ADDR_CHANGE)) 726a5c72737SRavi Kumar phy_data->sfp_diags = 1; 727a5c72737SRavi Kumar } 728a5c72737SRavi Kumar } else { 729a5c72737SRavi Kumar phy_data->sfp_changed = 0; 730a5c72737SRavi Kumar } 731a5c72737SRavi Kumar 732a5c72737SRavi Kumar put: 733a5c72737SRavi Kumar axgbe_phy_sfp_put_mux(pdata); 734a5c72737SRavi Kumar 735a5c72737SRavi Kumar return ret; 736a5c72737SRavi Kumar } 737a5c72737SRavi Kumar 738a5c72737SRavi Kumar static void axgbe_phy_sfp_signals(struct axgbe_port *pdata) 739a5c72737SRavi Kumar { 740a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 741a5c72737SRavi Kumar unsigned int gpio_input; 742a5c72737SRavi Kumar u8 gpio_reg, gpio_ports[2]; 743a5c72737SRavi Kumar int ret; 744a5c72737SRavi Kumar 745a5c72737SRavi Kumar /* Read the input port registers */ 746a5c72737SRavi Kumar gpio_reg = 0; 747a5c72737SRavi Kumar ret = axgbe_phy_i2c_read(pdata, phy_data->sfp_gpio_address, 748a5c72737SRavi Kumar &gpio_reg, sizeof(gpio_reg), 749a5c72737SRavi Kumar gpio_ports, sizeof(gpio_ports)); 750a5c72737SRavi Kumar if (ret) { 751a5c72737SRavi Kumar PMD_DRV_LOG(ERR, "I2C error reading SFP GPIOs\n"); 752a5c72737SRavi Kumar return; 753a5c72737SRavi Kumar } 754a5c72737SRavi Kumar 755a5c72737SRavi Kumar gpio_input = (gpio_ports[1] << 8) | gpio_ports[0]; 756a5c72737SRavi Kumar 757a5c72737SRavi Kumar if (phy_data->sfp_gpio_mask & AXGBE_GPIO_NO_MOD_ABSENT) { 758a5c72737SRavi Kumar /* No GPIO, just assume the module is present for now */ 759a5c72737SRavi Kumar phy_data->sfp_mod_absent = 0; 760a5c72737SRavi Kumar } else { 761a5c72737SRavi Kumar if (!(gpio_input & (1 << phy_data->sfp_gpio_mod_absent))) 762a5c72737SRavi Kumar phy_data->sfp_mod_absent = 0; 763a5c72737SRavi Kumar } 764a5c72737SRavi Kumar 765a5c72737SRavi Kumar if (!(phy_data->sfp_gpio_mask & AXGBE_GPIO_NO_RX_LOS) && 766a5c72737SRavi Kumar (gpio_input & (1 << phy_data->sfp_gpio_rx_los))) 767a5c72737SRavi Kumar phy_data->sfp_rx_los = 1; 768a5c72737SRavi Kumar 769a5c72737SRavi Kumar if (!(phy_data->sfp_gpio_mask & AXGBE_GPIO_NO_TX_FAULT) && 770a5c72737SRavi Kumar (gpio_input & (1 << phy_data->sfp_gpio_tx_fault))) 771a5c72737SRavi Kumar phy_data->sfp_tx_fault = 1; 772a5c72737SRavi Kumar } 773a5c72737SRavi Kumar 774a5c72737SRavi Kumar static void axgbe_phy_sfp_mod_absent(struct axgbe_port *pdata) 775a5c72737SRavi Kumar { 776a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 777a5c72737SRavi Kumar 778a5c72737SRavi Kumar phy_data->sfp_mod_absent = 1; 779a5c72737SRavi Kumar phy_data->sfp_phy_avail = 0; 780a5c72737SRavi Kumar memset(&phy_data->sfp_eeprom, 0, sizeof(phy_data->sfp_eeprom)); 781a5c72737SRavi Kumar } 782a5c72737SRavi Kumar 783a5c72737SRavi Kumar static void axgbe_phy_sfp_reset(struct axgbe_phy_data *phy_data) 784a5c72737SRavi Kumar { 785a5c72737SRavi Kumar phy_data->sfp_rx_los = 0; 786a5c72737SRavi Kumar phy_data->sfp_tx_fault = 0; 787a5c72737SRavi Kumar phy_data->sfp_mod_absent = 1; 788a5c72737SRavi Kumar phy_data->sfp_diags = 0; 789a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_UNKNOWN; 790a5c72737SRavi Kumar phy_data->sfp_cable = AXGBE_SFP_CABLE_UNKNOWN; 791a5c72737SRavi Kumar phy_data->sfp_speed = AXGBE_SFP_SPEED_UNKNOWN; 792a5c72737SRavi Kumar } 793a5c72737SRavi Kumar 7944216cdc0SChandu Babu N static const char *axgbe_base_as_string(enum axgbe_sfp_base sfp_base) 7954216cdc0SChandu Babu N { 7964216cdc0SChandu Babu N switch (sfp_base) { 7974216cdc0SChandu Babu N case AXGBE_SFP_BASE_1000_T: 7984216cdc0SChandu Babu N return "1G_T"; 7994216cdc0SChandu Babu N case AXGBE_SFP_BASE_1000_SX: 8004216cdc0SChandu Babu N return "1G_SX"; 8014216cdc0SChandu Babu N case AXGBE_SFP_BASE_1000_LX: 8024216cdc0SChandu Babu N return "1G_LX"; 8034216cdc0SChandu Babu N case AXGBE_SFP_BASE_1000_CX: 8044216cdc0SChandu Babu N return "1G_CX"; 8054216cdc0SChandu Babu N case AXGBE_SFP_BASE_10000_SR: 8064216cdc0SChandu Babu N return "10G_SR"; 8074216cdc0SChandu Babu N case AXGBE_SFP_BASE_10000_LR: 8084216cdc0SChandu Babu N return "10G_LR"; 8094216cdc0SChandu Babu N case AXGBE_SFP_BASE_10000_LRM: 8104216cdc0SChandu Babu N return "10G_LRM"; 8114216cdc0SChandu Babu N case AXGBE_SFP_BASE_10000_ER: 8124216cdc0SChandu Babu N return "10G_ER"; 8134216cdc0SChandu Babu N case AXGBE_SFP_BASE_10000_CR: 8144216cdc0SChandu Babu N return "10G_CR"; 8154216cdc0SChandu Babu N default: 8164216cdc0SChandu Babu N return "Unknown"; 8174216cdc0SChandu Babu N } 8184216cdc0SChandu Babu N } 8194216cdc0SChandu Babu N 820a5c72737SRavi Kumar static void axgbe_phy_sfp_detect(struct axgbe_port *pdata) 821a5c72737SRavi Kumar { 822a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 823a5c72737SRavi Kumar int ret; 824a5c72737SRavi Kumar 825a5c72737SRavi Kumar /* Reset the SFP signals and info */ 826a5c72737SRavi Kumar axgbe_phy_sfp_reset(phy_data); 827a5c72737SRavi Kumar 828a5c72737SRavi Kumar ret = axgbe_phy_get_comm_ownership(pdata); 829a5c72737SRavi Kumar if (ret) 830a5c72737SRavi Kumar return; 831a5c72737SRavi Kumar 832a5c72737SRavi Kumar /* Read the SFP signals and check for module presence */ 833a5c72737SRavi Kumar axgbe_phy_sfp_signals(pdata); 834a5c72737SRavi Kumar if (phy_data->sfp_mod_absent) { 835a5c72737SRavi Kumar axgbe_phy_sfp_mod_absent(pdata); 836a5c72737SRavi Kumar goto put; 837a5c72737SRavi Kumar } 838a5c72737SRavi Kumar 839a5c72737SRavi Kumar ret = axgbe_phy_sfp_read_eeprom(pdata); 840a5c72737SRavi Kumar if (ret) { 841a5c72737SRavi Kumar /* Treat any error as if there isn't an SFP plugged in */ 842a5c72737SRavi Kumar axgbe_phy_sfp_reset(phy_data); 843a5c72737SRavi Kumar axgbe_phy_sfp_mod_absent(pdata); 844a5c72737SRavi Kumar goto put; 845a5c72737SRavi Kumar } 846a5c72737SRavi Kumar 847a5c72737SRavi Kumar axgbe_phy_sfp_parse_eeprom(pdata); 848a5c72737SRavi Kumar axgbe_phy_sfp_external_phy(pdata); 849a5c72737SRavi Kumar 8504216cdc0SChandu Babu N PMD_DRV_LOG(DEBUG, "SFP Base: %s\n", 8514216cdc0SChandu Babu N axgbe_base_as_string(phy_data->sfp_base)); 8524216cdc0SChandu Babu N 853a5c72737SRavi Kumar put: 854a5c72737SRavi Kumar axgbe_phy_sfp_phy_settings(pdata); 855a5c72737SRavi Kumar axgbe_phy_put_comm_ownership(pdata); 856a5c72737SRavi Kumar } 857a5c72737SRavi Kumar 858a5c72737SRavi Kumar static void axgbe_phy_phydev_flowctrl(struct axgbe_port *pdata) 859a5c72737SRavi Kumar { 860a5c72737SRavi Kumar pdata->phy.tx_pause = 0; 861a5c72737SRavi Kumar pdata->phy.rx_pause = 0; 862a5c72737SRavi Kumar } 863a5c72737SRavi Kumar 864a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_an73_redrv_outcome(struct axgbe_port *pdata) 865a5c72737SRavi Kumar { 866a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 867a5c72737SRavi Kumar enum axgbe_mode mode; 868a5c72737SRavi Kumar unsigned int ad_reg, lp_reg; 869a5c72737SRavi Kumar 870a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_Autoneg; 871a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_Backplane; 872a5c72737SRavi Kumar 873a5c72737SRavi Kumar /* Use external PHY to determine flow control */ 874a5c72737SRavi Kumar if (pdata->phy.pause_autoneg) 875a5c72737SRavi Kumar axgbe_phy_phydev_flowctrl(pdata); 876a5c72737SRavi Kumar 877a5c72737SRavi Kumar /* Compare Advertisement and Link Partner register 2 */ 878a5c72737SRavi Kumar ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1); 879a5c72737SRavi Kumar lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1); 880a5c72737SRavi Kumar if (lp_reg & 0x80) 881a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full; 882a5c72737SRavi Kumar if (lp_reg & 0x20) 883a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full; 884a5c72737SRavi Kumar 885a5c72737SRavi Kumar ad_reg &= lp_reg; 886a5c72737SRavi Kumar if (ad_reg & 0x80) { 887a5c72737SRavi Kumar switch (phy_data->port_mode) { 888a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 889443ab5aaSSelwin Sebastian case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG: 890a5c72737SRavi Kumar mode = AXGBE_MODE_KR; 891a5c72737SRavi Kumar break; 892a5c72737SRavi Kumar default: 893a5c72737SRavi Kumar mode = AXGBE_MODE_SFI; 894a5c72737SRavi Kumar break; 895a5c72737SRavi Kumar } 896a5c72737SRavi Kumar } else if (ad_reg & 0x20) { 897a5c72737SRavi Kumar switch (phy_data->port_mode) { 898a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 899443ab5aaSSelwin Sebastian case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG: 900a5c72737SRavi Kumar mode = AXGBE_MODE_KX_1000; 901a5c72737SRavi Kumar break; 902a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 903a5c72737SRavi Kumar mode = AXGBE_MODE_X; 904a5c72737SRavi Kumar break; 905a5c72737SRavi Kumar case AXGBE_PORT_MODE_SFP: 906a5c72737SRavi Kumar switch (phy_data->sfp_base) { 907a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_T: 908a5c72737SRavi Kumar mode = AXGBE_MODE_SGMII_1000; 909a5c72737SRavi Kumar break; 910a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_SX: 911a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_LX: 912a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_CX: 913a5c72737SRavi Kumar default: 914a5c72737SRavi Kumar mode = AXGBE_MODE_X; 915a5c72737SRavi Kumar break; 916a5c72737SRavi Kumar } 917a5c72737SRavi Kumar break; 918a5c72737SRavi Kumar default: 919a5c72737SRavi Kumar mode = AXGBE_MODE_SGMII_1000; 920a5c72737SRavi Kumar break; 921a5c72737SRavi Kumar } 922a5c72737SRavi Kumar } else { 923a5c72737SRavi Kumar mode = AXGBE_MODE_UNKNOWN; 924a5c72737SRavi Kumar } 925a5c72737SRavi Kumar 926a5c72737SRavi Kumar /* Compare Advertisement and Link Partner register 3 */ 927a5c72737SRavi Kumar ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2); 928a5c72737SRavi Kumar lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2); 929a5c72737SRavi Kumar if (lp_reg & 0xc000) 930a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC; 931a5c72737SRavi Kumar 932a5c72737SRavi Kumar return mode; 933a5c72737SRavi Kumar } 934a5c72737SRavi Kumar 935a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_an73_outcome(struct axgbe_port *pdata) 936a5c72737SRavi Kumar { 937a5c72737SRavi Kumar enum axgbe_mode mode; 938a5c72737SRavi Kumar unsigned int ad_reg, lp_reg; 939a5c72737SRavi Kumar 940a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_Autoneg; 941a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_Backplane; 942a5c72737SRavi Kumar 943a5c72737SRavi Kumar /* Compare Advertisement and Link Partner register 1 */ 944a5c72737SRavi Kumar ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE); 945a5c72737SRavi Kumar lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA); 946a5c72737SRavi Kumar if (lp_reg & 0x400) 947a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_Pause; 948a5c72737SRavi Kumar if (lp_reg & 0x800) 949a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause; 950a5c72737SRavi Kumar 951a5c72737SRavi Kumar if (pdata->phy.pause_autoneg) { 952a5c72737SRavi Kumar /* Set flow control based on auto-negotiation result */ 953a5c72737SRavi Kumar pdata->phy.tx_pause = 0; 954a5c72737SRavi Kumar pdata->phy.rx_pause = 0; 955a5c72737SRavi Kumar 956a5c72737SRavi Kumar if (ad_reg & lp_reg & 0x400) { 957a5c72737SRavi Kumar pdata->phy.tx_pause = 1; 958a5c72737SRavi Kumar pdata->phy.rx_pause = 1; 959a5c72737SRavi Kumar } else if (ad_reg & lp_reg & 0x800) { 960a5c72737SRavi Kumar if (ad_reg & 0x400) 961a5c72737SRavi Kumar pdata->phy.rx_pause = 1; 962a5c72737SRavi Kumar else if (lp_reg & 0x400) 963a5c72737SRavi Kumar pdata->phy.tx_pause = 1; 964a5c72737SRavi Kumar } 965a5c72737SRavi Kumar } 966a5c72737SRavi Kumar 967a5c72737SRavi Kumar /* Compare Advertisement and Link Partner register 2 */ 968a5c72737SRavi Kumar ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1); 969a5c72737SRavi Kumar lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1); 970a5c72737SRavi Kumar if (lp_reg & 0x80) 971a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full; 972a5c72737SRavi Kumar if (lp_reg & 0x20) 973a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full; 974a5c72737SRavi Kumar 975a5c72737SRavi Kumar ad_reg &= lp_reg; 976a5c72737SRavi Kumar if (ad_reg & 0x80) 977a5c72737SRavi Kumar mode = AXGBE_MODE_KR; 978a5c72737SRavi Kumar else if (ad_reg & 0x20) 979a5c72737SRavi Kumar mode = AXGBE_MODE_KX_1000; 980a5c72737SRavi Kumar else 981a5c72737SRavi Kumar mode = AXGBE_MODE_UNKNOWN; 982a5c72737SRavi Kumar 983a5c72737SRavi Kumar /* Compare Advertisement and Link Partner register 3 */ 984a5c72737SRavi Kumar ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2); 985a5c72737SRavi Kumar lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2); 986a5c72737SRavi Kumar if (lp_reg & 0xc000) 987a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC; 988a5c72737SRavi Kumar 989a5c72737SRavi Kumar return mode; 990a5c72737SRavi Kumar } 991a5c72737SRavi Kumar 992102b6ec3SGirish Nandibasappa static enum axgbe_mode axgbe_phy_an37_sgmii_outcome(struct axgbe_port *pdata) 993102b6ec3SGirish Nandibasappa { 994102b6ec3SGirish Nandibasappa enum axgbe_mode mode; 995102b6ec3SGirish Nandibasappa 996102b6ec3SGirish Nandibasappa pdata->phy.lp_advertising |= ADVERTISED_Autoneg; 997102b6ec3SGirish Nandibasappa pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Full; 998102b6ec3SGirish Nandibasappa 999102b6ec3SGirish Nandibasappa if (pdata->phy.pause_autoneg) 1000102b6ec3SGirish Nandibasappa axgbe_phy_phydev_flowctrl(pdata); 1001102b6ec3SGirish Nandibasappa 1002102b6ec3SGirish Nandibasappa switch (pdata->an_status & AXGBE_SGMII_AN_LINK_SPEED) { 1003102b6ec3SGirish Nandibasappa case AXGBE_SGMII_AN_LINK_SPEED_100: 1004102b6ec3SGirish Nandibasappa if (pdata->an_status & AXGBE_SGMII_AN_LINK_DUPLEX) { 1005102b6ec3SGirish Nandibasappa pdata->phy.lp_advertising |= ADVERTISED_100baseT_Full; 1006102b6ec3SGirish Nandibasappa mode = AXGBE_MODE_SGMII_100; 1007102b6ec3SGirish Nandibasappa } else { 1008102b6ec3SGirish Nandibasappa mode = AXGBE_MODE_UNKNOWN; 1009102b6ec3SGirish Nandibasappa } 1010102b6ec3SGirish Nandibasappa break; 1011102b6ec3SGirish Nandibasappa case AXGBE_SGMII_AN_LINK_SPEED_1000: 1012102b6ec3SGirish Nandibasappa if (pdata->an_status & AXGBE_SGMII_AN_LINK_DUPLEX) { 1013102b6ec3SGirish Nandibasappa pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Full; 1014102b6ec3SGirish Nandibasappa mode = AXGBE_MODE_SGMII_1000; 1015102b6ec3SGirish Nandibasappa } else { 1016102b6ec3SGirish Nandibasappa /* Half-duplex not supported */ 1017102b6ec3SGirish Nandibasappa mode = AXGBE_MODE_UNKNOWN; 1018102b6ec3SGirish Nandibasappa } 1019102b6ec3SGirish Nandibasappa break; 1020102b6ec3SGirish Nandibasappa default: 1021102b6ec3SGirish Nandibasappa mode = AXGBE_MODE_UNKNOWN; 1022102b6ec3SGirish Nandibasappa break; 1023102b6ec3SGirish Nandibasappa } 1024102b6ec3SGirish Nandibasappa return mode; 1025102b6ec3SGirish Nandibasappa } 1026102b6ec3SGirish Nandibasappa 1027a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_an_outcome(struct axgbe_port *pdata) 1028a5c72737SRavi Kumar { 1029a5c72737SRavi Kumar switch (pdata->an_mode) { 1030a5c72737SRavi Kumar case AXGBE_AN_MODE_CL73: 1031a5c72737SRavi Kumar return axgbe_phy_an73_outcome(pdata); 1032a5c72737SRavi Kumar case AXGBE_AN_MODE_CL73_REDRV: 1033a5c72737SRavi Kumar return axgbe_phy_an73_redrv_outcome(pdata); 1034a5c72737SRavi Kumar case AXGBE_AN_MODE_CL37: 1035a5c72737SRavi Kumar case AXGBE_AN_MODE_CL37_SGMII: 1036102b6ec3SGirish Nandibasappa return axgbe_phy_an37_sgmii_outcome(pdata); 1037a5c72737SRavi Kumar default: 1038a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1039a5c72737SRavi Kumar } 1040a5c72737SRavi Kumar } 1041a5c72737SRavi Kumar 1042a5c72737SRavi Kumar static unsigned int axgbe_phy_an_advertising(struct axgbe_port *pdata) 1043a5c72737SRavi Kumar { 1044a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1045a5c72737SRavi Kumar unsigned int advertising; 1046a5c72737SRavi Kumar 1047a5c72737SRavi Kumar /* Without a re-driver, just return current advertising */ 1048a5c72737SRavi Kumar if (!phy_data->redrv) 1049a5c72737SRavi Kumar return pdata->phy.advertising; 1050a5c72737SRavi Kumar 1051a5c72737SRavi Kumar /* With the KR re-driver we need to advertise a single speed */ 1052a5c72737SRavi Kumar advertising = pdata->phy.advertising; 1053a5c72737SRavi Kumar advertising &= ~ADVERTISED_1000baseKX_Full; 1054a5c72737SRavi Kumar advertising &= ~ADVERTISED_10000baseKR_Full; 1055a5c72737SRavi Kumar 1056a5c72737SRavi Kumar switch (phy_data->port_mode) { 1057a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 1058443ab5aaSSelwin Sebastian case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG: 1059a5c72737SRavi Kumar advertising |= ADVERTISED_10000baseKR_Full; 1060a5c72737SRavi Kumar break; 1061a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 1062a5c72737SRavi Kumar advertising |= ADVERTISED_1000baseKX_Full; 1063a5c72737SRavi Kumar break; 1064a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 1065a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 1066a5c72737SRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 1067a5c72737SRavi Kumar advertising |= ADVERTISED_1000baseKX_Full; 1068a5c72737SRavi Kumar break; 1069a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 1070a5c72737SRavi Kumar PMD_DRV_LOG(ERR, "10GBASE_T mode is not supported\n"); 1071a5c72737SRavi Kumar break; 1072a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 1073a5c72737SRavi Kumar advertising |= ADVERTISED_10000baseKR_Full; 1074a5c72737SRavi Kumar break; 1075a5c72737SRavi Kumar case AXGBE_PORT_MODE_SFP: 1076a5c72737SRavi Kumar switch (phy_data->sfp_base) { 1077a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_T: 1078a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_SX: 1079a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_LX: 1080a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_CX: 1081a5c72737SRavi Kumar advertising |= ADVERTISED_1000baseKX_Full; 1082a5c72737SRavi Kumar break; 1083a5c72737SRavi Kumar default: 1084a5c72737SRavi Kumar advertising |= ADVERTISED_10000baseKR_Full; 1085a5c72737SRavi Kumar break; 1086a5c72737SRavi Kumar } 1087a5c72737SRavi Kumar break; 1088a5c72737SRavi Kumar default: 1089a5c72737SRavi Kumar advertising |= ADVERTISED_10000baseKR_Full; 1090a5c72737SRavi Kumar break; 1091a5c72737SRavi Kumar } 1092a5c72737SRavi Kumar 1093a5c72737SRavi Kumar return advertising; 1094a5c72737SRavi Kumar } 1095a5c72737SRavi Kumar 1096a5c72737SRavi Kumar static int axgbe_phy_an_config(struct axgbe_port *pdata __rte_unused) 1097a5c72737SRavi Kumar { 1098a5c72737SRavi Kumar return 0; 1099a5c72737SRavi Kumar /* Dummy API since there is no case to support 11007be78d02SJosh Soref * external phy devices registered through kernel APIs 1101a5c72737SRavi Kumar */ 1102a5c72737SRavi Kumar } 1103a5c72737SRavi Kumar 1104a5c72737SRavi Kumar static enum axgbe_an_mode axgbe_phy_an_sfp_mode(struct axgbe_phy_data *phy_data) 1105a5c72737SRavi Kumar { 1106a5c72737SRavi Kumar switch (phy_data->sfp_base) { 1107a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_T: 1108a5c72737SRavi Kumar return AXGBE_AN_MODE_CL37_SGMII; 1109a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_SX: 1110a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_LX: 1111a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_CX: 1112a5c72737SRavi Kumar return AXGBE_AN_MODE_CL37; 1113a5c72737SRavi Kumar default: 1114a5c72737SRavi Kumar return AXGBE_AN_MODE_NONE; 1115a5c72737SRavi Kumar } 1116a5c72737SRavi Kumar } 1117a5c72737SRavi Kumar 1118a5c72737SRavi Kumar static enum axgbe_an_mode axgbe_phy_an_mode(struct axgbe_port *pdata) 1119a5c72737SRavi Kumar { 1120a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1121a5c72737SRavi Kumar 1122a5c72737SRavi Kumar /* A KR re-driver will always require CL73 AN */ 1123a5c72737SRavi Kumar if (phy_data->redrv) 1124a5c72737SRavi Kumar return AXGBE_AN_MODE_CL73_REDRV; 1125a5c72737SRavi Kumar 1126a5c72737SRavi Kumar switch (phy_data->port_mode) { 1127a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 1128a5c72737SRavi Kumar return AXGBE_AN_MODE_CL73; 1129443ab5aaSSelwin Sebastian case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG: 1130a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 1131a5c72737SRavi Kumar return AXGBE_AN_MODE_NONE; 1132a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 1133a5c72737SRavi Kumar return AXGBE_AN_MODE_CL37_SGMII; 1134a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 1135a5c72737SRavi Kumar return AXGBE_AN_MODE_CL37; 1136a5c72737SRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 1137a5c72737SRavi Kumar return AXGBE_AN_MODE_CL37_SGMII; 1138a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 1139a5c72737SRavi Kumar return AXGBE_AN_MODE_CL73; 1140a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 1141a5c72737SRavi Kumar return AXGBE_AN_MODE_NONE; 1142a5c72737SRavi Kumar case AXGBE_PORT_MODE_SFP: 1143a5c72737SRavi Kumar return axgbe_phy_an_sfp_mode(phy_data); 1144a5c72737SRavi Kumar default: 1145a5c72737SRavi Kumar return AXGBE_AN_MODE_NONE; 1146a5c72737SRavi Kumar } 1147a5c72737SRavi Kumar } 1148a5c72737SRavi Kumar 1149a5c72737SRavi Kumar static int axgbe_phy_set_redrv_mode_mdio(struct axgbe_port *pdata, 1150a5c72737SRavi Kumar enum axgbe_phy_redrv_mode mode) 1151a5c72737SRavi Kumar { 1152a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1153a5c72737SRavi Kumar u16 redrv_reg, redrv_val; 1154a5c72737SRavi Kumar 1155a5c72737SRavi Kumar redrv_reg = AXGBE_PHY_REDRV_MODE_REG + (phy_data->redrv_lane * 0x1000); 1156a5c72737SRavi Kumar redrv_val = (u16)mode; 1157a5c72737SRavi Kumar 1158a5c72737SRavi Kumar return pdata->hw_if.write_ext_mii_regs(pdata, phy_data->redrv_addr, 1159a5c72737SRavi Kumar redrv_reg, redrv_val); 1160a5c72737SRavi Kumar } 1161a5c72737SRavi Kumar 1162a5c72737SRavi Kumar static int axgbe_phy_set_redrv_mode_i2c(struct axgbe_port *pdata, 1163a5c72737SRavi Kumar enum axgbe_phy_redrv_mode mode) 1164a5c72737SRavi Kumar { 1165a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1166a5c72737SRavi Kumar unsigned int redrv_reg; 1167a5c72737SRavi Kumar int ret; 1168a5c72737SRavi Kumar 1169a5c72737SRavi Kumar /* Calculate the register to write */ 1170a5c72737SRavi Kumar redrv_reg = AXGBE_PHY_REDRV_MODE_REG + (phy_data->redrv_lane * 0x1000); 1171a5c72737SRavi Kumar 1172a5c72737SRavi Kumar ret = axgbe_phy_redrv_write(pdata, redrv_reg, mode); 1173a5c72737SRavi Kumar 1174a5c72737SRavi Kumar return ret; 1175a5c72737SRavi Kumar } 1176a5c72737SRavi Kumar 1177a5c72737SRavi Kumar static void axgbe_phy_set_redrv_mode(struct axgbe_port *pdata) 1178a5c72737SRavi Kumar { 1179a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1180a5c72737SRavi Kumar enum axgbe_phy_redrv_mode mode; 1181a5c72737SRavi Kumar int ret; 1182a5c72737SRavi Kumar 1183a5c72737SRavi Kumar if (!phy_data->redrv) 1184a5c72737SRavi Kumar return; 1185a5c72737SRavi Kumar 1186a5c72737SRavi Kumar mode = AXGBE_PHY_REDRV_MODE_CX; 1187a5c72737SRavi Kumar if ((phy_data->port_mode == AXGBE_PORT_MODE_SFP) && 1188a5c72737SRavi Kumar (phy_data->sfp_base != AXGBE_SFP_BASE_1000_CX) && 1189a5c72737SRavi Kumar (phy_data->sfp_base != AXGBE_SFP_BASE_10000_CR)) 1190a5c72737SRavi Kumar mode = AXGBE_PHY_REDRV_MODE_SR; 1191a5c72737SRavi Kumar 1192a5c72737SRavi Kumar ret = axgbe_phy_get_comm_ownership(pdata); 1193a5c72737SRavi Kumar if (ret) 1194a5c72737SRavi Kumar return; 1195a5c72737SRavi Kumar 1196a5c72737SRavi Kumar if (phy_data->redrv_if) 1197a5c72737SRavi Kumar axgbe_phy_set_redrv_mode_i2c(pdata, mode); 1198a5c72737SRavi Kumar else 1199a5c72737SRavi Kumar axgbe_phy_set_redrv_mode_mdio(pdata, mode); 1200a5c72737SRavi Kumar 1201a5c72737SRavi Kumar axgbe_phy_put_comm_ownership(pdata); 1202a5c72737SRavi Kumar } 1203a5c72737SRavi Kumar 1204cd48955bSSelwin Sebastian static void axgbe_phy_rx_reset(struct axgbe_port *pdata) 1205cd48955bSSelwin Sebastian { 1206cd48955bSSelwin Sebastian int reg; 1207cd48955bSSelwin Sebastian 1208cd48955bSSelwin Sebastian reg = XMDIO_READ_BITS(pdata, MDIO_MMD_PCS, MDIO_PCS_DIGITAL_STAT, 1209cd48955bSSelwin Sebastian XGBE_PCS_PSEQ_STATE_MASK); 1210cd48955bSSelwin Sebastian if (reg == XGBE_PCS_PSEQ_STATE_POWER_GOOD) { 1211cd48955bSSelwin Sebastian /* Mailbox command timed out, reset of RX block is required. 1212cd48955bSSelwin Sebastian * This can be done by asseting the reset bit and wait for 1213cd48955bSSelwin Sebastian * its compeletion. 1214cd48955bSSelwin Sebastian */ 1215cd48955bSSelwin Sebastian XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1, 1216cd48955bSSelwin Sebastian XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_ON); 1217cd48955bSSelwin Sebastian rte_delay_us(20); 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_OFF); 1220cd48955bSSelwin Sebastian rte_delay_us(45); 1221cd48955bSSelwin Sebastian PMD_DRV_LOG(ERR, "firmware mailbox reset performed\n"); 1222cd48955bSSelwin Sebastian } 1223cd48955bSSelwin Sebastian } 1224cd48955bSSelwin Sebastian 1225cd48955bSSelwin Sebastian 122609b0a36cSSelwin Sebastian static void axgbe_phy_pll_ctrl(struct axgbe_port *pdata, bool enable) 122709b0a36cSSelwin Sebastian { 122809b0a36cSSelwin Sebastian XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_MISC_CTRL0, 122909b0a36cSSelwin Sebastian XGBE_PMA_PLL_CTRL_MASK, 123009b0a36cSSelwin Sebastian enable ? XGBE_PMA_PLL_CTRL_SET 123109b0a36cSSelwin Sebastian : XGBE_PMA_PLL_CTRL_CLEAR); 123209b0a36cSSelwin Sebastian 123309b0a36cSSelwin Sebastian /* Wait for command to complete */ 123409b0a36cSSelwin Sebastian rte_delay_us(150); 123509b0a36cSSelwin Sebastian } 123609b0a36cSSelwin Sebastian 12370df8d8dfSSelwin Sebastian static void axgbe_phy_perform_ratechange(struct axgbe_port *pdata, 12380df8d8dfSSelwin Sebastian unsigned int cmd, unsigned int sub_cmd) 1239a5c72737SRavi Kumar { 12400df8d8dfSSelwin Sebastian unsigned int s0 = 0; 12410df8d8dfSSelwin Sebastian unsigned int wait; 124209b0a36cSSelwin Sebastian /* Clear the PLL so that it helps in power down sequence */ 124309b0a36cSSelwin Sebastian axgbe_phy_pll_ctrl(pdata, false); 124409b0a36cSSelwin Sebastian 12454216cdc0SChandu Babu N /* Log if a previous command did not complete */ 1246cd48955bSSelwin Sebastian if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) { 12474216cdc0SChandu Babu N PMD_DRV_LOG(NOTICE, "firmware mailbox not ready for command\n"); 1248cd48955bSSelwin Sebastian axgbe_phy_rx_reset(pdata); 1249cd48955bSSelwin Sebastian } 1250a5c72737SRavi Kumar 12510df8d8dfSSelwin Sebastian /* Construct the command */ 12520df8d8dfSSelwin Sebastian XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, cmd); 12530df8d8dfSSelwin Sebastian XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, sub_cmd); 12540df8d8dfSSelwin Sebastian 12550df8d8dfSSelwin Sebastian /* Issue the command */ 12560df8d8dfSSelwin Sebastian XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0); 12570df8d8dfSSelwin Sebastian XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0); 12580df8d8dfSSelwin Sebastian XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1); 1259a5c72737SRavi Kumar 1260a5c72737SRavi Kumar /* Wait for command to complete */ 1261a5c72737SRavi Kumar wait = AXGBE_RATECHANGE_COUNT; 1262a5c72737SRavi Kumar while (wait--) { 1263a5c72737SRavi Kumar if (!XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) 126409b0a36cSSelwin Sebastian goto reenable_pll; 1265a5c72737SRavi Kumar rte_delay_us(1500); 1266a5c72737SRavi Kumar } 1267cd48955bSSelwin Sebastian PMD_DRV_LOG(NOTICE, "firmware mailbox command did not complete\n"); 1268cd48955bSSelwin Sebastian /* Reset on error */ 1269cd48955bSSelwin Sebastian axgbe_phy_rx_reset(pdata); 127009b0a36cSSelwin Sebastian 127109b0a36cSSelwin Sebastian reenable_pll: 127209b0a36cSSelwin Sebastian /* Re-enable the PLL control */ 127309b0a36cSSelwin Sebastian axgbe_phy_pll_ctrl(pdata, true); 127409b0a36cSSelwin Sebastian 12754216cdc0SChandu Babu N PMD_DRV_LOG(NOTICE, "firmware mailbox command did not complete\n"); 1276a5c72737SRavi Kumar } 1277a5c72737SRavi Kumar 1278a5c72737SRavi Kumar static void axgbe_phy_rrc(struct axgbe_port *pdata) 1279a5c72737SRavi Kumar { 1280a5c72737SRavi Kumar 1281a5c72737SRavi Kumar 1282a5c72737SRavi Kumar /* Receiver Reset Cycle */ 12830df8d8dfSSelwin Sebastian axgbe_phy_perform_ratechange(pdata, 5, 0); 12844216cdc0SChandu Babu N 12854216cdc0SChandu Babu N PMD_DRV_LOG(DEBUG, "receiver reset complete\n"); 1286a5c72737SRavi Kumar } 1287a5c72737SRavi Kumar 1288a5c72737SRavi Kumar static void axgbe_phy_power_off(struct axgbe_port *pdata) 1289a5c72737SRavi Kumar { 1290a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1291a5c72737SRavi Kumar 12920df8d8dfSSelwin Sebastian /* Power off */ 12930df8d8dfSSelwin Sebastian axgbe_phy_perform_ratechange(pdata, 0, 0); 1294a5c72737SRavi Kumar 1295a5c72737SRavi Kumar phy_data->cur_mode = AXGBE_MODE_UNKNOWN; 12964216cdc0SChandu Babu N 12974216cdc0SChandu Babu N PMD_DRV_LOG(DEBUG, "phy powered off\n"); 1298a5c72737SRavi Kumar } 1299a5c72737SRavi Kumar 1300a5c72737SRavi Kumar static void axgbe_phy_sfi_mode(struct axgbe_port *pdata) 1301a5c72737SRavi Kumar { 1302a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1303a5c72737SRavi Kumar 1304a5c72737SRavi Kumar axgbe_phy_set_redrv_mode(pdata); 1305a5c72737SRavi Kumar 1306a5c72737SRavi Kumar /* 10G/SFI */ 1307a5c72737SRavi Kumar if (phy_data->sfp_cable != AXGBE_SFP_CABLE_PASSIVE) { 13080df8d8dfSSelwin Sebastian axgbe_phy_perform_ratechange(pdata, 3, 0); 1309a5c72737SRavi Kumar } else { 1310a5c72737SRavi Kumar if (phy_data->sfp_cable_len <= 1) 13110df8d8dfSSelwin Sebastian axgbe_phy_perform_ratechange(pdata, 3, 1); 1312a5c72737SRavi Kumar else if (phy_data->sfp_cable_len <= 3) 13130df8d8dfSSelwin Sebastian axgbe_phy_perform_ratechange(pdata, 3, 2); 1314a5c72737SRavi Kumar else 13150df8d8dfSSelwin Sebastian axgbe_phy_perform_ratechange(pdata, 3, 3); 1316a5c72737SRavi Kumar } 1317a5c72737SRavi Kumar 1318a5c72737SRavi Kumar phy_data->cur_mode = AXGBE_MODE_SFI; 13194216cdc0SChandu Babu N 13204216cdc0SChandu Babu N PMD_DRV_LOG(DEBUG, "10GbE SFI mode set\n"); 1321a5c72737SRavi Kumar } 1322a5c72737SRavi Kumar 1323a5c72737SRavi Kumar static void axgbe_phy_kr_mode(struct axgbe_port *pdata) 1324a5c72737SRavi Kumar { 1325a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1326a5c72737SRavi Kumar 1327a5c72737SRavi Kumar axgbe_phy_set_redrv_mode(pdata); 1328a5c72737SRavi Kumar 1329a5c72737SRavi Kumar /* 10G/KR */ 13300df8d8dfSSelwin Sebastian axgbe_phy_perform_ratechange(pdata, 4, 0); 1331a5c72737SRavi Kumar phy_data->cur_mode = AXGBE_MODE_KR; 13324216cdc0SChandu Babu N 13334216cdc0SChandu Babu N PMD_DRV_LOG(DEBUG, "10GbE KR mode set\n"); 1334a5c72737SRavi Kumar } 1335a5c72737SRavi Kumar 1336936e294cSGirish Nandibasappa static void axgbe_phy_kx_2500_mode(struct axgbe_port *pdata) 1337936e294cSGirish Nandibasappa { 1338936e294cSGirish Nandibasappa struct axgbe_phy_data *phy_data = pdata->phy_data; 1339936e294cSGirish Nandibasappa 1340936e294cSGirish Nandibasappa axgbe_phy_set_redrv_mode(pdata); 13410df8d8dfSSelwin Sebastian 1342936e294cSGirish Nandibasappa /* 2.5G/KX */ 13430df8d8dfSSelwin Sebastian axgbe_phy_perform_ratechange(pdata, 2, 0); 1344936e294cSGirish Nandibasappa phy_data->cur_mode = AXGBE_MODE_KX_2500; 1345936e294cSGirish Nandibasappa } 1346936e294cSGirish Nandibasappa 1347936e294cSGirish Nandibasappa static void axgbe_phy_sgmii_1000_mode(struct axgbe_port *pdata) 1348936e294cSGirish Nandibasappa { 1349936e294cSGirish Nandibasappa struct axgbe_phy_data *phy_data = pdata->phy_data; 1350936e294cSGirish Nandibasappa 1351936e294cSGirish Nandibasappa axgbe_phy_set_redrv_mode(pdata); 1352936e294cSGirish Nandibasappa 1353936e294cSGirish Nandibasappa /* 1G/SGMII */ 13540df8d8dfSSelwin Sebastian axgbe_phy_perform_ratechange(pdata, 1, 2); 1355936e294cSGirish Nandibasappa 1356936e294cSGirish Nandibasappa phy_data->cur_mode = AXGBE_MODE_SGMII_1000; 1357936e294cSGirish Nandibasappa } 1358936e294cSGirish Nandibasappa 1359a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_cur_mode(struct axgbe_port *pdata) 1360a5c72737SRavi Kumar { 1361a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1362a5c72737SRavi Kumar 1363a5c72737SRavi Kumar return phy_data->cur_mode; 1364a5c72737SRavi Kumar } 1365a5c72737SRavi Kumar 1366a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_switch_baset_mode(struct axgbe_port *pdata) 1367a5c72737SRavi Kumar { 1368a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1369a5c72737SRavi Kumar 1370a5c72737SRavi Kumar /* No switching if not 10GBase-T */ 1371a5c72737SRavi Kumar if (phy_data->port_mode != AXGBE_PORT_MODE_10GBASE_T) 1372a5c72737SRavi Kumar return axgbe_phy_cur_mode(pdata); 1373a5c72737SRavi Kumar 1374a5c72737SRavi Kumar switch (axgbe_phy_cur_mode(pdata)) { 1375a5c72737SRavi Kumar case AXGBE_MODE_SGMII_100: 1376a5c72737SRavi Kumar case AXGBE_MODE_SGMII_1000: 1377a5c72737SRavi Kumar return AXGBE_MODE_KR; 1378a5c72737SRavi Kumar case AXGBE_MODE_KR: 1379a5c72737SRavi Kumar default: 1380a5c72737SRavi Kumar return AXGBE_MODE_SGMII_1000; 1381a5c72737SRavi Kumar } 1382a5c72737SRavi Kumar } 1383a5c72737SRavi Kumar 1384a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_switch_bp_2500_mode(struct axgbe_port *pdata 1385a5c72737SRavi Kumar __rte_unused) 1386a5c72737SRavi Kumar { 1387a5c72737SRavi Kumar return AXGBE_MODE_KX_2500; 1388a5c72737SRavi Kumar } 1389a5c72737SRavi Kumar 1390a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_switch_bp_mode(struct axgbe_port *pdata) 1391a5c72737SRavi Kumar { 1392a5c72737SRavi Kumar /* If we are in KR switch to KX, and vice-versa */ 1393a5c72737SRavi Kumar switch (axgbe_phy_cur_mode(pdata)) { 1394a5c72737SRavi Kumar case AXGBE_MODE_KX_1000: 1395a5c72737SRavi Kumar return AXGBE_MODE_KR; 1396a5c72737SRavi Kumar case AXGBE_MODE_KR: 1397a5c72737SRavi Kumar default: 1398a5c72737SRavi Kumar return AXGBE_MODE_KX_1000; 1399a5c72737SRavi Kumar } 1400a5c72737SRavi Kumar } 1401a5c72737SRavi Kumar 1402a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_switch_mode(struct axgbe_port *pdata) 1403a5c72737SRavi Kumar { 1404a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1405a5c72737SRavi Kumar 1406a5c72737SRavi Kumar switch (phy_data->port_mode) { 1407a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 1408443ab5aaSSelwin Sebastian case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG: 1409a5c72737SRavi Kumar return axgbe_phy_switch_bp_mode(pdata); 1410a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 1411a5c72737SRavi Kumar return axgbe_phy_switch_bp_2500_mode(pdata); 1412a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 1413a5c72737SRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 1414a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 1415a5c72737SRavi Kumar return axgbe_phy_switch_baset_mode(pdata); 1416a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 1417a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 1418a5c72737SRavi Kumar case AXGBE_PORT_MODE_SFP: 1419a5c72737SRavi Kumar /* No switching, so just return current mode */ 1420a5c72737SRavi Kumar return axgbe_phy_cur_mode(pdata); 1421a5c72737SRavi Kumar default: 1422a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1423a5c72737SRavi Kumar } 1424a5c72737SRavi Kumar } 1425a5c72737SRavi Kumar 1426a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_basex_mode(struct axgbe_phy_data *phy_data 1427a5c72737SRavi Kumar __rte_unused, 1428a5c72737SRavi Kumar int speed) 1429a5c72737SRavi Kumar { 1430a5c72737SRavi Kumar switch (speed) { 1431a5c72737SRavi Kumar case SPEED_1000: 1432a5c72737SRavi Kumar return AXGBE_MODE_X; 1433a5c72737SRavi Kumar case SPEED_10000: 1434a5c72737SRavi Kumar return AXGBE_MODE_KR; 1435a5c72737SRavi Kumar default: 1436a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1437a5c72737SRavi Kumar } 1438a5c72737SRavi Kumar } 1439a5c72737SRavi Kumar 1440a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_baset_mode(struct axgbe_phy_data *phy_data 1441a5c72737SRavi Kumar __rte_unused, 1442a5c72737SRavi Kumar int speed) 1443a5c72737SRavi Kumar { 1444a5c72737SRavi Kumar switch (speed) { 1445a5c72737SRavi Kumar case SPEED_100: 1446a5c72737SRavi Kumar return AXGBE_MODE_SGMII_100; 1447a5c72737SRavi Kumar case SPEED_1000: 1448a5c72737SRavi Kumar return AXGBE_MODE_SGMII_1000; 1449a5c72737SRavi Kumar case SPEED_10000: 1450a5c72737SRavi Kumar return AXGBE_MODE_KR; 1451a5c72737SRavi Kumar default: 1452a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1453a5c72737SRavi Kumar } 1454a5c72737SRavi Kumar } 1455a5c72737SRavi Kumar 1456a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_sfp_mode(struct axgbe_phy_data *phy_data, 1457a5c72737SRavi Kumar int speed) 1458a5c72737SRavi Kumar { 1459a5c72737SRavi Kumar switch (speed) { 1460a5c72737SRavi Kumar case SPEED_100: 1461a5c72737SRavi Kumar return AXGBE_MODE_SGMII_100; 1462a5c72737SRavi Kumar case SPEED_1000: 1463a5c72737SRavi Kumar if (phy_data->sfp_base == AXGBE_SFP_BASE_1000_T) 1464a5c72737SRavi Kumar return AXGBE_MODE_SGMII_1000; 1465a5c72737SRavi Kumar else 1466a5c72737SRavi Kumar return AXGBE_MODE_X; 1467a5c72737SRavi Kumar case SPEED_10000: 1468a5c72737SRavi Kumar case SPEED_UNKNOWN: 1469a5c72737SRavi Kumar return AXGBE_MODE_SFI; 1470a5c72737SRavi Kumar default: 1471a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1472a5c72737SRavi Kumar } 1473a5c72737SRavi Kumar } 1474a5c72737SRavi Kumar 1475a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_bp_2500_mode(int speed) 1476a5c72737SRavi Kumar { 1477a5c72737SRavi Kumar switch (speed) { 1478a5c72737SRavi Kumar case SPEED_2500: 1479a5c72737SRavi Kumar return AXGBE_MODE_KX_2500; 1480a5c72737SRavi Kumar default: 1481a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1482a5c72737SRavi Kumar } 1483a5c72737SRavi Kumar } 1484a5c72737SRavi Kumar 1485a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_bp_mode(int speed) 1486a5c72737SRavi Kumar { 1487a5c72737SRavi Kumar switch (speed) { 1488a5c72737SRavi Kumar case SPEED_1000: 1489a5c72737SRavi Kumar return AXGBE_MODE_KX_1000; 1490a5c72737SRavi Kumar case SPEED_10000: 1491a5c72737SRavi Kumar return AXGBE_MODE_KR; 1492a5c72737SRavi Kumar default: 1493a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1494a5c72737SRavi Kumar } 1495a5c72737SRavi Kumar } 1496a5c72737SRavi Kumar 1497a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_mode(struct axgbe_port *pdata, 1498a5c72737SRavi Kumar int speed) 1499a5c72737SRavi Kumar { 1500a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1501a5c72737SRavi Kumar 1502a5c72737SRavi Kumar switch (phy_data->port_mode) { 1503a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 1504443ab5aaSSelwin Sebastian case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG: 1505a5c72737SRavi Kumar return axgbe_phy_get_bp_mode(speed); 1506a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 1507a5c72737SRavi Kumar return axgbe_phy_get_bp_2500_mode(speed); 1508a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 1509a5c72737SRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 1510a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 1511a5c72737SRavi Kumar return axgbe_phy_get_baset_mode(phy_data, speed); 1512a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 1513a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 1514a5c72737SRavi Kumar return axgbe_phy_get_basex_mode(phy_data, speed); 1515a5c72737SRavi Kumar case AXGBE_PORT_MODE_SFP: 1516a5c72737SRavi Kumar return axgbe_phy_get_sfp_mode(phy_data, speed); 1517a5c72737SRavi Kumar default: 1518a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1519a5c72737SRavi Kumar } 1520a5c72737SRavi Kumar } 1521a5c72737SRavi Kumar 1522a5c72737SRavi Kumar static void axgbe_phy_set_mode(struct axgbe_port *pdata, enum axgbe_mode mode) 1523a5c72737SRavi Kumar { 1524a5c72737SRavi Kumar switch (mode) { 1525a5c72737SRavi Kumar case AXGBE_MODE_KR: 1526a5c72737SRavi Kumar axgbe_phy_kr_mode(pdata); 1527a5c72737SRavi Kumar break; 1528a5c72737SRavi Kumar case AXGBE_MODE_SFI: 1529a5c72737SRavi Kumar axgbe_phy_sfi_mode(pdata); 1530a5c72737SRavi Kumar break; 1531936e294cSGirish Nandibasappa case AXGBE_MODE_KX_2500: 1532936e294cSGirish Nandibasappa axgbe_phy_kx_2500_mode(pdata); 1533936e294cSGirish Nandibasappa break; 1534936e294cSGirish Nandibasappa case AXGBE_MODE_SGMII_1000: 1535936e294cSGirish Nandibasappa axgbe_phy_sgmii_1000_mode(pdata); 1536936e294cSGirish Nandibasappa break; 1537a5c72737SRavi Kumar default: 1538a5c72737SRavi Kumar break; 1539a5c72737SRavi Kumar } 1540a5c72737SRavi Kumar } 1541a5c72737SRavi Kumar 1542a5c72737SRavi Kumar static bool axgbe_phy_check_mode(struct axgbe_port *pdata, 1543a5c72737SRavi Kumar enum axgbe_mode mode, u32 advert) 1544a5c72737SRavi Kumar { 1545a5c72737SRavi Kumar if (pdata->phy.autoneg == AUTONEG_ENABLE) { 1546a5c72737SRavi Kumar if (pdata->phy.advertising & advert) 1547a5c72737SRavi Kumar return true; 1548a5c72737SRavi Kumar } else { 1549a5c72737SRavi Kumar enum axgbe_mode cur_mode; 1550a5c72737SRavi Kumar 1551a5c72737SRavi Kumar cur_mode = axgbe_phy_get_mode(pdata, pdata->phy.speed); 1552a5c72737SRavi Kumar if (cur_mode == mode) 1553a5c72737SRavi Kumar return true; 1554a5c72737SRavi Kumar } 1555a5c72737SRavi Kumar 1556a5c72737SRavi Kumar return false; 1557a5c72737SRavi Kumar } 1558a5c72737SRavi Kumar 1559a5c72737SRavi Kumar static bool axgbe_phy_use_basex_mode(struct axgbe_port *pdata, 1560a5c72737SRavi Kumar enum axgbe_mode mode) 1561a5c72737SRavi Kumar { 1562a5c72737SRavi Kumar switch (mode) { 1563a5c72737SRavi Kumar case AXGBE_MODE_X: 1564a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1565a5c72737SRavi Kumar ADVERTISED_1000baseT_Full); 1566a5c72737SRavi Kumar case AXGBE_MODE_KR: 1567a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1568a5c72737SRavi Kumar ADVERTISED_10000baseT_Full); 1569a5c72737SRavi Kumar default: 1570a5c72737SRavi Kumar return false; 1571a5c72737SRavi Kumar } 1572a5c72737SRavi Kumar } 1573a5c72737SRavi Kumar 1574a5c72737SRavi Kumar static bool axgbe_phy_use_baset_mode(struct axgbe_port *pdata, 1575a5c72737SRavi Kumar enum axgbe_mode mode) 1576a5c72737SRavi Kumar { 1577a5c72737SRavi Kumar switch (mode) { 1578a5c72737SRavi Kumar case AXGBE_MODE_SGMII_100: 1579a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1580a5c72737SRavi Kumar ADVERTISED_100baseT_Full); 1581a5c72737SRavi Kumar case AXGBE_MODE_SGMII_1000: 1582a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1583a5c72737SRavi Kumar ADVERTISED_1000baseT_Full); 1584a5c72737SRavi Kumar case AXGBE_MODE_KR: 1585a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1586a5c72737SRavi Kumar ADVERTISED_10000baseT_Full); 1587a5c72737SRavi Kumar default: 1588a5c72737SRavi Kumar return false; 1589a5c72737SRavi Kumar } 1590a5c72737SRavi Kumar } 1591a5c72737SRavi Kumar 1592a5c72737SRavi Kumar static bool axgbe_phy_use_sfp_mode(struct axgbe_port *pdata, 1593a5c72737SRavi Kumar enum axgbe_mode mode) 1594a5c72737SRavi Kumar { 1595a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1596a5c72737SRavi Kumar 1597a5c72737SRavi Kumar switch (mode) { 1598a5c72737SRavi Kumar case AXGBE_MODE_X: 1599a5c72737SRavi Kumar if (phy_data->sfp_base == AXGBE_SFP_BASE_1000_T) 1600a5c72737SRavi Kumar return false; 1601a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1602a5c72737SRavi Kumar ADVERTISED_1000baseT_Full); 1603a5c72737SRavi Kumar case AXGBE_MODE_SGMII_100: 1604a5c72737SRavi Kumar if (phy_data->sfp_base != AXGBE_SFP_BASE_1000_T) 1605a5c72737SRavi Kumar return false; 1606a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1607a5c72737SRavi Kumar ADVERTISED_100baseT_Full); 1608a5c72737SRavi Kumar case AXGBE_MODE_SGMII_1000: 1609a5c72737SRavi Kumar if (phy_data->sfp_base != AXGBE_SFP_BASE_1000_T) 1610a5c72737SRavi Kumar return false; 1611a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1612a5c72737SRavi Kumar ADVERTISED_1000baseT_Full); 1613a5c72737SRavi Kumar case AXGBE_MODE_SFI: 1614a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1615a5c72737SRavi Kumar ADVERTISED_10000baseT_Full); 1616a5c72737SRavi Kumar default: 1617a5c72737SRavi Kumar return false; 1618a5c72737SRavi Kumar } 1619a5c72737SRavi Kumar } 1620a5c72737SRavi Kumar 1621a5c72737SRavi Kumar static bool axgbe_phy_use_bp_2500_mode(struct axgbe_port *pdata, 1622a5c72737SRavi Kumar enum axgbe_mode mode) 1623a5c72737SRavi Kumar { 1624a5c72737SRavi Kumar switch (mode) { 1625a5c72737SRavi Kumar case AXGBE_MODE_KX_2500: 1626a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1627a5c72737SRavi Kumar ADVERTISED_2500baseX_Full); 1628a5c72737SRavi Kumar default: 1629a5c72737SRavi Kumar return false; 1630a5c72737SRavi Kumar } 1631a5c72737SRavi Kumar } 1632a5c72737SRavi Kumar 1633a5c72737SRavi Kumar static bool axgbe_phy_use_bp_mode(struct axgbe_port *pdata, 1634a5c72737SRavi Kumar enum axgbe_mode mode) 1635a5c72737SRavi Kumar { 1636a5c72737SRavi Kumar switch (mode) { 1637a5c72737SRavi Kumar case AXGBE_MODE_KX_1000: 1638a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1639a5c72737SRavi Kumar ADVERTISED_1000baseKX_Full); 1640a5c72737SRavi Kumar case AXGBE_MODE_KR: 1641a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1642a5c72737SRavi Kumar ADVERTISED_10000baseKR_Full); 1643a5c72737SRavi Kumar default: 1644a5c72737SRavi Kumar return false; 1645a5c72737SRavi Kumar } 1646a5c72737SRavi Kumar } 1647a5c72737SRavi Kumar 1648a5c72737SRavi Kumar static bool axgbe_phy_use_mode(struct axgbe_port *pdata, enum axgbe_mode mode) 1649a5c72737SRavi Kumar { 1650a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1651a5c72737SRavi Kumar 1652a5c72737SRavi Kumar switch (phy_data->port_mode) { 1653a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 1654443ab5aaSSelwin Sebastian case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG: 1655a5c72737SRavi Kumar return axgbe_phy_use_bp_mode(pdata, mode); 1656a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 1657a5c72737SRavi Kumar return axgbe_phy_use_bp_2500_mode(pdata, mode); 1658a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 1659a5c72737SRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 1660a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 1661a5c72737SRavi Kumar return axgbe_phy_use_baset_mode(pdata, mode); 1662a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 1663a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 1664a5c72737SRavi Kumar return axgbe_phy_use_basex_mode(pdata, mode); 1665a5c72737SRavi Kumar case AXGBE_PORT_MODE_SFP: 1666a5c72737SRavi Kumar return axgbe_phy_use_sfp_mode(pdata, mode); 1667a5c72737SRavi Kumar default: 1668a5c72737SRavi Kumar return false; 1669a5c72737SRavi Kumar } 1670a5c72737SRavi Kumar } 1671a5c72737SRavi Kumar 1672a5c72737SRavi Kumar static int axgbe_phy_link_status(struct axgbe_port *pdata, int *an_restart) 1673a5c72737SRavi Kumar { 1674a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1675a5c72737SRavi Kumar unsigned int reg; 1676a5c72737SRavi Kumar 1677a5c72737SRavi Kumar *an_restart = 0; 1678a5c72737SRavi Kumar 1679a5c72737SRavi Kumar if (phy_data->port_mode == AXGBE_PORT_MODE_SFP) { 1680a5c72737SRavi Kumar /* Check SFP signals */ 1681a5c72737SRavi Kumar axgbe_phy_sfp_detect(pdata); 1682a5c72737SRavi Kumar 1683a5c72737SRavi Kumar if (phy_data->sfp_changed) { 1684a5c72737SRavi Kumar *an_restart = 1; 1685a5c72737SRavi Kumar return 0; 1686a5c72737SRavi Kumar } 1687a5c72737SRavi Kumar 1688a5c72737SRavi Kumar if (phy_data->sfp_mod_absent || phy_data->sfp_rx_los) 1689a5c72737SRavi Kumar return 0; 1690a5c72737SRavi Kumar } 1691a5c72737SRavi Kumar 1692a5c72737SRavi Kumar /* Link status is latched low, so read once to clear 1693a5c72737SRavi Kumar * and then read again to get current state 1694a5c72737SRavi Kumar */ 1695a5c72737SRavi Kumar reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1); 1696a5c72737SRavi Kumar reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1); 1697a5c72737SRavi Kumar if (reg & MDIO_STAT1_LSTATUS) 1698a5c72737SRavi Kumar return 1; 1699a5c72737SRavi Kumar 1700a5c72737SRavi Kumar /* No link, attempt a receiver reset cycle */ 1701a5c72737SRavi Kumar if (phy_data->rrc_count++) { 1702a5c72737SRavi Kumar phy_data->rrc_count = 0; 1703a5c72737SRavi Kumar axgbe_phy_rrc(pdata); 1704a5c72737SRavi Kumar } 1705a5c72737SRavi Kumar 1706a5c72737SRavi Kumar return 0; 1707a5c72737SRavi Kumar } 1708a5c72737SRavi Kumar 17094ac7516bSRavi Kumar static void axgbe_phy_sfp_gpio_setup(struct axgbe_port *pdata) 17104ac7516bSRavi Kumar { 17114ac7516bSRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 17124ac7516bSRavi Kumar 17134ac7516bSRavi Kumar phy_data->sfp_gpio_address = AXGBE_GPIO_ADDRESS_PCA9555 + 1714*a3ec01b4SVenkat Kumar Ande XP_GET_BITS(pdata->pp3, XP_PROP_3, GPIO_ADDR); 17154ac7516bSRavi Kumar 1716*a3ec01b4SVenkat Kumar Ande phy_data->sfp_gpio_mask = XP_GET_BITS(pdata->pp3, XP_PROP_3, GPIO_MASK); 17174ac7516bSRavi Kumar 1718*a3ec01b4SVenkat Kumar Ande phy_data->sfp_gpio_rx_los = XP_GET_BITS(pdata->pp3, XP_PROP_3, 17194ac7516bSRavi Kumar GPIO_RX_LOS); 1720*a3ec01b4SVenkat Kumar Ande phy_data->sfp_gpio_tx_fault = XP_GET_BITS(pdata->pp3, XP_PROP_3, 17214ac7516bSRavi Kumar GPIO_TX_FAULT); 1722*a3ec01b4SVenkat Kumar Ande phy_data->sfp_gpio_mod_absent = XP_GET_BITS(pdata->pp3, XP_PROP_3, 17234ac7516bSRavi Kumar GPIO_MOD_ABS); 1724*a3ec01b4SVenkat Kumar Ande phy_data->sfp_gpio_rate_select = XP_GET_BITS(pdata->pp3, XP_PROP_3, 17254ac7516bSRavi Kumar GPIO_RATE_SELECT); 17264ac7516bSRavi Kumar } 17274ac7516bSRavi Kumar 17284ac7516bSRavi Kumar static void axgbe_phy_sfp_comm_setup(struct axgbe_port *pdata) 17294ac7516bSRavi Kumar { 17304ac7516bSRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1731*a3ec01b4SVenkat Kumar Ande unsigned int mux_addr_hi, mux_addr_lo; 17324ac7516bSRavi Kumar 1733*a3ec01b4SVenkat Kumar Ande mux_addr_hi = XP_GET_BITS(pdata->pp4, XP_PROP_4, MUX_ADDR_HI); 1734*a3ec01b4SVenkat Kumar Ande mux_addr_lo = XP_GET_BITS(pdata->pp4, XP_PROP_4, MUX_ADDR_LO); 17354ac7516bSRavi Kumar if (mux_addr_lo == AXGBE_SFP_DIRECT) 17364ac7516bSRavi Kumar return; 17374ac7516bSRavi Kumar 17384ac7516bSRavi Kumar phy_data->sfp_comm = AXGBE_SFP_COMM_PCA9545; 17394ac7516bSRavi Kumar phy_data->sfp_mux_address = (mux_addr_hi << 2) + mux_addr_lo; 1740*a3ec01b4SVenkat Kumar Ande phy_data->sfp_mux_channel = XP_GET_BITS(pdata->pp4, XP_PROP_4, MUX_CHAN); 17414ac7516bSRavi Kumar } 17424ac7516bSRavi Kumar 17434ac7516bSRavi Kumar static void axgbe_phy_sfp_setup(struct axgbe_port *pdata) 17444ac7516bSRavi Kumar { 17454ac7516bSRavi Kumar axgbe_phy_sfp_comm_setup(pdata); 17464ac7516bSRavi Kumar axgbe_phy_sfp_gpio_setup(pdata); 17474ac7516bSRavi Kumar } 17484ac7516bSRavi Kumar 17494ac7516bSRavi Kumar static bool axgbe_phy_redrv_error(struct axgbe_phy_data *phy_data) 17504ac7516bSRavi Kumar { 17514ac7516bSRavi Kumar if (!phy_data->redrv) 17524ac7516bSRavi Kumar return false; 17534ac7516bSRavi Kumar 17544ac7516bSRavi Kumar if (phy_data->redrv_if >= AXGBE_PHY_REDRV_IF_MAX) 17554ac7516bSRavi Kumar return true; 17564ac7516bSRavi Kumar 17574ac7516bSRavi Kumar switch (phy_data->redrv_model) { 17584ac7516bSRavi Kumar case AXGBE_PHY_REDRV_MODEL_4223: 17594ac7516bSRavi Kumar if (phy_data->redrv_lane > 3) 17604ac7516bSRavi Kumar return true; 17614ac7516bSRavi Kumar break; 17624ac7516bSRavi Kumar case AXGBE_PHY_REDRV_MODEL_4227: 17634ac7516bSRavi Kumar if (phy_data->redrv_lane > 1) 17644ac7516bSRavi Kumar return true; 17654ac7516bSRavi Kumar break; 17664ac7516bSRavi Kumar default: 17674ac7516bSRavi Kumar return true; 17684ac7516bSRavi Kumar } 17694ac7516bSRavi Kumar 17704ac7516bSRavi Kumar return false; 17714ac7516bSRavi Kumar } 17724ac7516bSRavi Kumar 17734ac7516bSRavi Kumar static int axgbe_phy_mdio_reset_setup(struct axgbe_port *pdata) 17744ac7516bSRavi Kumar { 17754ac7516bSRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 17764ac7516bSRavi Kumar 17774ac7516bSRavi Kumar if (phy_data->conn_type != AXGBE_CONN_TYPE_MDIO) 17784ac7516bSRavi Kumar return 0; 1779*a3ec01b4SVenkat Kumar Ande 1780*a3ec01b4SVenkat Kumar Ande phy_data->mdio_reset = XP_GET_BITS(pdata->pp3, XP_PROP_3, MDIO_RESET); 17814ac7516bSRavi Kumar switch (phy_data->mdio_reset) { 17824ac7516bSRavi Kumar case AXGBE_MDIO_RESET_NONE: 17834ac7516bSRavi Kumar case AXGBE_MDIO_RESET_I2C_GPIO: 17844ac7516bSRavi Kumar case AXGBE_MDIO_RESET_INT_GPIO: 17854ac7516bSRavi Kumar break; 17864ac7516bSRavi Kumar default: 17874ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "unsupported MDIO reset (%#x)\n", 17884ac7516bSRavi Kumar phy_data->mdio_reset); 17894ac7516bSRavi Kumar return -EINVAL; 17904ac7516bSRavi Kumar } 17914ac7516bSRavi Kumar if (phy_data->mdio_reset == AXGBE_MDIO_RESET_I2C_GPIO) { 17924ac7516bSRavi Kumar phy_data->mdio_reset_addr = AXGBE_GPIO_ADDRESS_PCA9555 + 1793*a3ec01b4SVenkat Kumar Ande XP_GET_BITS(pdata->pp3, XP_PROP_3, 17944ac7516bSRavi Kumar MDIO_RESET_I2C_ADDR); 1795*a3ec01b4SVenkat Kumar Ande phy_data->mdio_reset_gpio = XP_GET_BITS(pdata->pp3, XP_PROP_3, 17964ac7516bSRavi Kumar MDIO_RESET_I2C_GPIO); 17974ac7516bSRavi Kumar } else if (phy_data->mdio_reset == AXGBE_MDIO_RESET_INT_GPIO) { 1798*a3ec01b4SVenkat Kumar Ande phy_data->mdio_reset_gpio = XP_GET_BITS(pdata->pp3, XP_PROP_3, 17994ac7516bSRavi Kumar MDIO_RESET_INT_GPIO); 18004ac7516bSRavi Kumar } 18014ac7516bSRavi Kumar 18024ac7516bSRavi Kumar return 0; 18034ac7516bSRavi Kumar } 18044ac7516bSRavi Kumar 18054ac7516bSRavi Kumar static bool axgbe_phy_port_mode_mismatch(struct axgbe_port *pdata) 18064ac7516bSRavi Kumar { 18074ac7516bSRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 18084ac7516bSRavi Kumar 18094ac7516bSRavi Kumar switch (phy_data->port_mode) { 18104ac7516bSRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 1811443ab5aaSSelwin Sebastian case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG: 18124ac7516bSRavi Kumar if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) || 18134ac7516bSRavi Kumar (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000)) 18144ac7516bSRavi Kumar return false; 18154ac7516bSRavi Kumar break; 18164ac7516bSRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 18174ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500) 18184ac7516bSRavi Kumar return false; 18194ac7516bSRavi Kumar break; 18204ac7516bSRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 18214ac7516bSRavi Kumar if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) || 18224ac7516bSRavi Kumar (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000)) 18234ac7516bSRavi Kumar return false; 18244ac7516bSRavi Kumar break; 18254ac7516bSRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 18264ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) 18274ac7516bSRavi Kumar return false; 18284ac7516bSRavi Kumar break; 18294ac7516bSRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 18304ac7516bSRavi Kumar if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) || 18314ac7516bSRavi Kumar (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) || 18324ac7516bSRavi Kumar (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500)) 18334ac7516bSRavi Kumar return false; 18344ac7516bSRavi Kumar break; 18354ac7516bSRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 18364ac7516bSRavi Kumar if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) || 18374ac7516bSRavi Kumar (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) || 18384ac7516bSRavi Kumar (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000)) 18394ac7516bSRavi Kumar return false; 18404ac7516bSRavi Kumar break; 18414ac7516bSRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 18424ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) 18434ac7516bSRavi Kumar return false; 18444ac7516bSRavi Kumar break; 18454ac7516bSRavi Kumar case AXGBE_PORT_MODE_SFP: 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 default: 18524ac7516bSRavi Kumar break; 18534ac7516bSRavi Kumar } 18544ac7516bSRavi Kumar 18554ac7516bSRavi Kumar return true; 18564ac7516bSRavi Kumar } 18574ac7516bSRavi Kumar 18584ac7516bSRavi Kumar static bool axgbe_phy_conn_type_mismatch(struct axgbe_port *pdata) 18594ac7516bSRavi Kumar { 18604ac7516bSRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 18614ac7516bSRavi Kumar 18624ac7516bSRavi Kumar switch (phy_data->port_mode) { 18634ac7516bSRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 1864443ab5aaSSelwin Sebastian case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG: 18654ac7516bSRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 18664ac7516bSRavi Kumar if (phy_data->conn_type == AXGBE_CONN_TYPE_BACKPLANE) 18674ac7516bSRavi Kumar return false; 18684ac7516bSRavi Kumar break; 18694ac7516bSRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 18704ac7516bSRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 18714ac7516bSRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 18724ac7516bSRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 18734ac7516bSRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 18744ac7516bSRavi Kumar if (phy_data->conn_type == AXGBE_CONN_TYPE_MDIO) 18754ac7516bSRavi Kumar return false; 18764ac7516bSRavi Kumar break; 18774ac7516bSRavi Kumar case AXGBE_PORT_MODE_SFP: 18784ac7516bSRavi Kumar if (phy_data->conn_type == AXGBE_CONN_TYPE_SFP) 18794ac7516bSRavi Kumar return false; 18804ac7516bSRavi Kumar break; 18814ac7516bSRavi Kumar default: 18824ac7516bSRavi Kumar break; 18834ac7516bSRavi Kumar } 18844ac7516bSRavi Kumar 18854ac7516bSRavi Kumar return true; 18864ac7516bSRavi Kumar } 18874ac7516bSRavi Kumar 18884ac7516bSRavi Kumar static bool axgbe_phy_port_enabled(struct axgbe_port *pdata) 18894ac7516bSRavi Kumar { 1890*a3ec01b4SVenkat Kumar Ande if (!XP_GET_BITS(pdata->pp0, XP_PROP_0, PORT_SPEEDS)) 18914ac7516bSRavi Kumar return false; 1892*a3ec01b4SVenkat Kumar Ande if (!XP_GET_BITS(pdata->pp0, XP_PROP_0, CONN_TYPE)) 18934ac7516bSRavi Kumar return false; 18944ac7516bSRavi Kumar 18954ac7516bSRavi Kumar return true; 18964ac7516bSRavi Kumar } 18974ac7516bSRavi Kumar 189800072056SRavi Kumar static void axgbe_phy_cdr_track(struct axgbe_port *pdata) 189900072056SRavi Kumar { 190000072056SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 190100072056SRavi Kumar 190200072056SRavi Kumar if (!pdata->vdata->an_cdr_workaround) 190300072056SRavi Kumar return; 190400072056SRavi Kumar 190500072056SRavi Kumar if (!phy_data->phy_cdr_notrack) 190600072056SRavi Kumar return; 190700072056SRavi Kumar 190800072056SRavi Kumar rte_delay_us(phy_data->phy_cdr_delay + 400); 190900072056SRavi Kumar 191000072056SRavi Kumar XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_CDR_CONTROL, 191100072056SRavi Kumar AXGBE_PMA_CDR_TRACK_EN_MASK, 191200072056SRavi Kumar AXGBE_PMA_CDR_TRACK_EN_ON); 191300072056SRavi Kumar 191400072056SRavi Kumar phy_data->phy_cdr_notrack = 0; 191500072056SRavi Kumar } 191600072056SRavi Kumar 191700072056SRavi Kumar static void axgbe_phy_cdr_notrack(struct axgbe_port *pdata) 191800072056SRavi Kumar { 191900072056SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 192000072056SRavi Kumar 192100072056SRavi Kumar if (!pdata->vdata->an_cdr_workaround) 192200072056SRavi Kumar return; 192300072056SRavi Kumar 192400072056SRavi Kumar if (phy_data->phy_cdr_notrack) 192500072056SRavi Kumar return; 192600072056SRavi Kumar 192700072056SRavi Kumar XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_CDR_CONTROL, 192800072056SRavi Kumar AXGBE_PMA_CDR_TRACK_EN_MASK, 192900072056SRavi Kumar AXGBE_PMA_CDR_TRACK_EN_OFF); 193000072056SRavi Kumar 193100072056SRavi Kumar axgbe_phy_rrc(pdata); 193200072056SRavi Kumar 193300072056SRavi Kumar phy_data->phy_cdr_notrack = 1; 193400072056SRavi Kumar } 193500072056SRavi Kumar 193600072056SRavi Kumar static void axgbe_phy_kr_training_post(struct axgbe_port *pdata) 193700072056SRavi Kumar { 193800072056SRavi Kumar if (!pdata->cdr_track_early) 193900072056SRavi Kumar axgbe_phy_cdr_track(pdata); 194000072056SRavi Kumar } 194100072056SRavi Kumar 194200072056SRavi Kumar static void axgbe_phy_kr_training_pre(struct axgbe_port *pdata) 194300072056SRavi Kumar { 194400072056SRavi Kumar if (pdata->cdr_track_early) 194500072056SRavi Kumar axgbe_phy_cdr_track(pdata); 194600072056SRavi Kumar } 194700072056SRavi Kumar 194800072056SRavi Kumar static void axgbe_phy_an_post(struct axgbe_port *pdata) 194900072056SRavi Kumar { 195000072056SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 195100072056SRavi Kumar 195200072056SRavi Kumar switch (pdata->an_mode) { 195300072056SRavi Kumar case AXGBE_AN_MODE_CL73: 195400072056SRavi Kumar case AXGBE_AN_MODE_CL73_REDRV: 195500072056SRavi Kumar if (phy_data->cur_mode != AXGBE_MODE_KR) 195600072056SRavi Kumar break; 195700072056SRavi Kumar 195800072056SRavi Kumar axgbe_phy_cdr_track(pdata); 195900072056SRavi Kumar 196000072056SRavi Kumar switch (pdata->an_result) { 196100072056SRavi Kumar case AXGBE_AN_READY: 196200072056SRavi Kumar case AXGBE_AN_COMPLETE: 196300072056SRavi Kumar break; 196400072056SRavi Kumar default: 196500072056SRavi Kumar if (phy_data->phy_cdr_delay < AXGBE_CDR_DELAY_MAX) 196600072056SRavi Kumar phy_data->phy_cdr_delay += AXGBE_CDR_DELAY_INC; 196700072056SRavi Kumar break; 196800072056SRavi Kumar } 196900072056SRavi Kumar break; 197000072056SRavi Kumar default: 197100072056SRavi Kumar break; 197200072056SRavi Kumar } 197300072056SRavi Kumar } 197400072056SRavi Kumar 197500072056SRavi Kumar static void axgbe_phy_an_pre(struct axgbe_port *pdata) 197600072056SRavi Kumar { 197700072056SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 197800072056SRavi Kumar 197900072056SRavi Kumar switch (pdata->an_mode) { 198000072056SRavi Kumar case AXGBE_AN_MODE_CL73: 198100072056SRavi Kumar case AXGBE_AN_MODE_CL73_REDRV: 198200072056SRavi Kumar if (phy_data->cur_mode != AXGBE_MODE_KR) 198300072056SRavi Kumar break; 198400072056SRavi Kumar 198500072056SRavi Kumar axgbe_phy_cdr_notrack(pdata); 198600072056SRavi Kumar break; 198700072056SRavi Kumar default: 198800072056SRavi Kumar break; 198900072056SRavi Kumar } 199000072056SRavi Kumar } 199100072056SRavi Kumar 1992a5c72737SRavi Kumar static void axgbe_phy_stop(struct axgbe_port *pdata) 1993a5c72737SRavi Kumar { 1994a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1995a5c72737SRavi Kumar 1996a5c72737SRavi Kumar /* Reset SFP data */ 1997a5c72737SRavi Kumar axgbe_phy_sfp_reset(phy_data); 1998a5c72737SRavi Kumar axgbe_phy_sfp_mod_absent(pdata); 1999a5c72737SRavi Kumar 200000072056SRavi Kumar /* Reset CDR support */ 200100072056SRavi Kumar axgbe_phy_cdr_track(pdata); 200200072056SRavi Kumar 2003a5c72737SRavi Kumar /* Power off the PHY */ 2004a5c72737SRavi Kumar axgbe_phy_power_off(pdata); 2005a5c72737SRavi Kumar 2006a5c72737SRavi Kumar /* Stop the I2C controller */ 2007a5c72737SRavi Kumar pdata->i2c_if.i2c_stop(pdata); 2008a5c72737SRavi Kumar } 2009a5c72737SRavi Kumar 2010a5c72737SRavi Kumar static int axgbe_phy_start(struct axgbe_port *pdata) 2011a5c72737SRavi Kumar { 2012a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 2013a5c72737SRavi Kumar int ret; 2014a5c72737SRavi Kumar 2015a5c72737SRavi Kumar /* Start the I2C controller */ 2016a5c72737SRavi Kumar ret = pdata->i2c_if.i2c_start(pdata); 2017a5c72737SRavi Kumar if (ret) 2018a5c72737SRavi Kumar return ret; 2019a5c72737SRavi Kumar 2020a5c72737SRavi Kumar /* Start in highest supported mode */ 2021a5c72737SRavi Kumar axgbe_phy_set_mode(pdata, phy_data->start_mode); 2022a5c72737SRavi Kumar 202300072056SRavi Kumar /* Reset CDR support */ 202400072056SRavi Kumar axgbe_phy_cdr_track(pdata); 202500072056SRavi Kumar 2026a5c72737SRavi Kumar /* After starting the I2C controller, we can check for an SFP */ 2027a5c72737SRavi Kumar switch (phy_data->port_mode) { 2028a5c72737SRavi Kumar case AXGBE_PORT_MODE_SFP: 2029a5c72737SRavi Kumar axgbe_phy_sfp_detect(pdata); 2030a5c72737SRavi Kumar break; 2031a5c72737SRavi Kumar default: 2032a5c72737SRavi Kumar break; 2033a5c72737SRavi Kumar } 2034102b6ec3SGirish Nandibasappa pdata->phy.advertising &= axgbe_phy_an_advertising(pdata); 2035a5c72737SRavi Kumar 2036a5c72737SRavi Kumar return ret; 2037a5c72737SRavi Kumar } 2038a5c72737SRavi Kumar 2039a5c72737SRavi Kumar static int axgbe_phy_reset(struct axgbe_port *pdata) 2040a5c72737SRavi Kumar { 2041a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 2042a5c72737SRavi Kumar enum axgbe_mode cur_mode; 2043a5c72737SRavi Kumar 2044a5c72737SRavi Kumar /* Reset by power cycling the PHY */ 2045a5c72737SRavi Kumar cur_mode = phy_data->cur_mode; 2046a5c72737SRavi Kumar axgbe_phy_power_off(pdata); 2047a5c72737SRavi Kumar /* First time reset is done with passed unknown mode*/ 2048a5c72737SRavi Kumar axgbe_phy_set_mode(pdata, cur_mode); 2049a5c72737SRavi Kumar return 0; 2050a5c72737SRavi Kumar } 2051a5c72737SRavi Kumar 20524ac7516bSRavi Kumar static int axgbe_phy_init(struct axgbe_port *pdata) 20534ac7516bSRavi Kumar { 20544ac7516bSRavi Kumar struct axgbe_phy_data *phy_data; 20554ac7516bSRavi Kumar int ret; 20564ac7516bSRavi Kumar 20574ac7516bSRavi Kumar /* Check if enabled */ 20584ac7516bSRavi Kumar if (!axgbe_phy_port_enabled(pdata)) { 20594ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "device is not enabled\n"); 20604ac7516bSRavi Kumar return -ENODEV; 20614ac7516bSRavi Kumar } 20624ac7516bSRavi Kumar 20634ac7516bSRavi Kumar /* Initialize the I2C controller */ 20644ac7516bSRavi Kumar ret = pdata->i2c_if.i2c_init(pdata); 20654ac7516bSRavi Kumar if (ret) 20664ac7516bSRavi Kumar return ret; 20674ac7516bSRavi Kumar 20684ac7516bSRavi Kumar phy_data = rte_zmalloc("phy_data memory", sizeof(*phy_data), 0); 20694ac7516bSRavi Kumar if (!phy_data) { 20704ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "phy_data allocation failed\n"); 20714ac7516bSRavi Kumar return -ENOMEM; 20724ac7516bSRavi Kumar } 20734ac7516bSRavi Kumar pdata->phy_data = phy_data; 20744ac7516bSRavi Kumar 2075*a3ec01b4SVenkat Kumar Ande phy_data->port_mode = XP_GET_BITS(pdata->pp0, XP_PROP_0, PORT_MODE); 2076*a3ec01b4SVenkat Kumar Ande phy_data->port_id = XP_GET_BITS(pdata->pp0, XP_PROP_0, PORT_ID); 2077*a3ec01b4SVenkat Kumar Ande phy_data->port_speeds = XP_GET_BITS(pdata->pp0, XP_PROP_0, PORT_SPEEDS); 2078*a3ec01b4SVenkat Kumar Ande phy_data->conn_type = XP_GET_BITS(pdata->pp0, XP_PROP_0, CONN_TYPE); 2079*a3ec01b4SVenkat Kumar Ande phy_data->mdio_addr = XP_GET_BITS(pdata->pp0, XP_PROP_0, MDIO_ADDR); 20804ac7516bSRavi Kumar 2081*a3ec01b4SVenkat Kumar Ande phy_data->redrv = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_PRESENT); 2082*a3ec01b4SVenkat Kumar Ande phy_data->redrv_if = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_IF); 2083*a3ec01b4SVenkat Kumar Ande phy_data->redrv_addr = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_ADDR); 2084*a3ec01b4SVenkat Kumar Ande phy_data->redrv_lane = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_LANE); 2085*a3ec01b4SVenkat Kumar Ande phy_data->redrv_model = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_MODEL); 20864ac7516bSRavi Kumar 20874ac7516bSRavi Kumar /* Validate the connection requested */ 20884ac7516bSRavi Kumar if (axgbe_phy_conn_type_mismatch(pdata)) { 20894ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "phy mode/connection mismatch (%#x/%#x)\n", 20904ac7516bSRavi Kumar phy_data->port_mode, phy_data->conn_type); 20914ac7516bSRavi Kumar return -EINVAL; 20924ac7516bSRavi Kumar } 20934ac7516bSRavi Kumar 20944ac7516bSRavi Kumar /* Validate the mode requested */ 20954ac7516bSRavi Kumar if (axgbe_phy_port_mode_mismatch(pdata)) { 20964ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "phy mode/speed mismatch (%#x/%#x)\n", 20974ac7516bSRavi Kumar phy_data->port_mode, phy_data->port_speeds); 20984ac7516bSRavi Kumar return -EINVAL; 20994ac7516bSRavi Kumar } 21004ac7516bSRavi Kumar 21014ac7516bSRavi Kumar /* Check for and validate MDIO reset support */ 21024ac7516bSRavi Kumar ret = axgbe_phy_mdio_reset_setup(pdata); 21034ac7516bSRavi Kumar if (ret) 21044ac7516bSRavi Kumar return ret; 21054ac7516bSRavi Kumar 21064ac7516bSRavi Kumar /* Validate the re-driver information */ 21074ac7516bSRavi Kumar if (axgbe_phy_redrv_error(phy_data)) { 21084ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "phy re-driver settings error\n"); 21094ac7516bSRavi Kumar return -EINVAL; 21104ac7516bSRavi Kumar } 21114ac7516bSRavi Kumar pdata->kr_redrv = phy_data->redrv; 21124ac7516bSRavi Kumar 21134ac7516bSRavi Kumar /* Indicate current mode is unknown */ 21144ac7516bSRavi Kumar phy_data->cur_mode = AXGBE_MODE_UNKNOWN; 21154ac7516bSRavi Kumar 21164ac7516bSRavi Kumar /* Initialize supported features */ 21174ac7516bSRavi Kumar pdata->phy.supported = 0; 21184ac7516bSRavi Kumar 21194ac7516bSRavi Kumar switch (phy_data->port_mode) { 21204ac7516bSRavi Kumar /* Backplane support */ 21214ac7516bSRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 21224ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Autoneg; 2123443ab5aaSSelwin Sebastian /* Fallthrough */ 2124443ab5aaSSelwin Sebastian case AXGBE_PORT_MODE_BACKPLANE_NO_AUTONEG: 21254ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 21264ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Backplane; 21274ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { 21284ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_1000baseKX_Full; 21294ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_KX_1000; 21304ac7516bSRavi Kumar } 21314ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) { 21324ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_10000baseKR_Full; 21334ac7516bSRavi Kumar if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) 21344ac7516bSRavi Kumar pdata->phy.supported |= 21354ac7516bSRavi Kumar SUPPORTED_10000baseR_FEC; 21364ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_KR; 21374ac7516bSRavi Kumar } 21384ac7516bSRavi Kumar 21394ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE; 21404ac7516bSRavi Kumar break; 21414ac7516bSRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 21424ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 21434ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Backplane; 21444ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_2500baseX_Full; 21454ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_KX_2500; 21464ac7516bSRavi Kumar 21474ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE; 21484ac7516bSRavi Kumar break; 21494ac7516bSRavi Kumar 21504ac7516bSRavi Kumar /* MDIO 1GBase-T support */ 21514ac7516bSRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 21524ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Autoneg; 21534ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 21544ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_TP; 21554ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) { 21564ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_100baseT_Full; 21574ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_100; 21584ac7516bSRavi Kumar } 21594ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { 21604ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_1000baseT_Full; 21614ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_1000; 21624ac7516bSRavi Kumar } 21634ac7516bSRavi Kumar 21644ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_CL22; 21654ac7516bSRavi Kumar break; 21664ac7516bSRavi Kumar 21674ac7516bSRavi Kumar /* MDIO Base-X support */ 21684ac7516bSRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 21694ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Autoneg; 21704ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 21714ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_FIBRE; 21724ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_1000baseT_Full; 21734ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_X; 21744ac7516bSRavi Kumar 21754ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_CL22; 21764ac7516bSRavi Kumar break; 21774ac7516bSRavi Kumar 21784ac7516bSRavi Kumar /* MDIO NBase-T support */ 21794ac7516bSRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 21804ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Autoneg; 21814ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 21824ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_TP; 21834ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) { 21844ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_100baseT_Full; 21854ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_100; 21864ac7516bSRavi Kumar } 21874ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { 21884ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_1000baseT_Full; 21894ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_1000; 21904ac7516bSRavi Kumar } 21914ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500) { 21924ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_2500baseX_Full; 21934ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_KX_2500; 21944ac7516bSRavi Kumar } 21954ac7516bSRavi Kumar 21964ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_CL45; 21974ac7516bSRavi Kumar break; 21984ac7516bSRavi Kumar 21994ac7516bSRavi Kumar /* 10GBase-T support */ 22004ac7516bSRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 22014ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Autoneg; 22024ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 22034ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_TP; 22044ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) { 22054ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_100baseT_Full; 22064ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_100; 22074ac7516bSRavi Kumar } 22084ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { 22094ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_1000baseT_Full; 22104ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_1000; 22114ac7516bSRavi Kumar } 22124ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) { 22134ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_10000baseT_Full; 22144ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_KR; 22154ac7516bSRavi Kumar } 22164ac7516bSRavi Kumar 22174ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE; 22184ac7516bSRavi Kumar break; 22194ac7516bSRavi Kumar 22204ac7516bSRavi Kumar /* 10GBase-R support */ 22214ac7516bSRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 22224ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Autoneg; 22234ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 22244ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_TP; 22254ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_10000baseT_Full; 22264ac7516bSRavi Kumar if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) 22274ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_10000baseR_FEC; 22284ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SFI; 22294ac7516bSRavi Kumar 22304ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE; 22314ac7516bSRavi Kumar break; 22324ac7516bSRavi Kumar 22334ac7516bSRavi Kumar /* SFP support */ 22344ac7516bSRavi Kumar case AXGBE_PORT_MODE_SFP: 22354ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Autoneg; 22364ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 22374ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_TP; 22384ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_FIBRE; 22394ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) { 22404ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_100baseT_Full; 22414ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_100; 22424ac7516bSRavi Kumar } 22434ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { 22444ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_1000baseT_Full; 22454ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_1000; 22464ac7516bSRavi Kumar } 22474ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) { 22484ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_10000baseT_Full; 22494ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SFI; 22504ac7516bSRavi Kumar if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) 22514ac7516bSRavi Kumar pdata->phy.supported |= 22524ac7516bSRavi Kumar SUPPORTED_10000baseR_FEC; 22534ac7516bSRavi Kumar } 22544ac7516bSRavi Kumar 22554ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_CL22; 22564ac7516bSRavi Kumar 22574ac7516bSRavi Kumar axgbe_phy_sfp_setup(pdata); 22584ac7516bSRavi Kumar break; 22594ac7516bSRavi Kumar default: 22604ac7516bSRavi Kumar return -EINVAL; 22614ac7516bSRavi Kumar } 22624ac7516bSRavi Kumar 22634ac7516bSRavi Kumar if ((phy_data->conn_type & AXGBE_CONN_TYPE_MDIO) && 22644ac7516bSRavi Kumar (phy_data->phydev_mode != AXGBE_MDIO_MODE_NONE)) { 22654ac7516bSRavi Kumar ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->mdio_addr, 22664ac7516bSRavi Kumar phy_data->phydev_mode); 22674ac7516bSRavi Kumar if (ret) { 22684ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "mdio port/clause not compatible (%d/%u)\n", 22694ac7516bSRavi Kumar phy_data->mdio_addr, phy_data->phydev_mode); 22704ac7516bSRavi Kumar return -EINVAL; 22714ac7516bSRavi Kumar } 22724ac7516bSRavi Kumar } 22734ac7516bSRavi Kumar 22744ac7516bSRavi Kumar if (phy_data->redrv && !phy_data->redrv_if) { 22754ac7516bSRavi Kumar ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->redrv_addr, 22764ac7516bSRavi Kumar AXGBE_MDIO_MODE_CL22); 22774ac7516bSRavi Kumar if (ret) { 22784ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "redriver mdio port not compatible (%u)\n", 22794ac7516bSRavi Kumar phy_data->redrv_addr); 22804ac7516bSRavi Kumar return -EINVAL; 22814ac7516bSRavi Kumar } 22824ac7516bSRavi Kumar } 228300072056SRavi Kumar 228400072056SRavi Kumar phy_data->phy_cdr_delay = AXGBE_CDR_DELAY_INIT; 22854ac7516bSRavi Kumar return 0; 22864ac7516bSRavi Kumar } 22874ac7516bSRavi Kumar void axgbe_init_function_ptrs_phy_v2(struct axgbe_phy_if *phy_if) 22884ac7516bSRavi Kumar { 22894ac7516bSRavi Kumar struct axgbe_phy_impl_if *phy_impl = &phy_if->phy_impl; 22904ac7516bSRavi Kumar 22914ac7516bSRavi Kumar phy_impl->init = axgbe_phy_init; 2292a5c72737SRavi Kumar phy_impl->reset = axgbe_phy_reset; 2293a5c72737SRavi Kumar phy_impl->start = axgbe_phy_start; 2294a5c72737SRavi Kumar phy_impl->stop = axgbe_phy_stop; 2295a5c72737SRavi Kumar phy_impl->link_status = axgbe_phy_link_status; 2296a5c72737SRavi Kumar phy_impl->use_mode = axgbe_phy_use_mode; 2297a5c72737SRavi Kumar phy_impl->set_mode = axgbe_phy_set_mode; 2298a5c72737SRavi Kumar phy_impl->get_mode = axgbe_phy_get_mode; 2299a5c72737SRavi Kumar phy_impl->switch_mode = axgbe_phy_switch_mode; 2300a5c72737SRavi Kumar phy_impl->cur_mode = axgbe_phy_cur_mode; 2301a5c72737SRavi Kumar phy_impl->an_mode = axgbe_phy_an_mode; 2302a5c72737SRavi Kumar phy_impl->an_config = axgbe_phy_an_config; 2303a5c72737SRavi Kumar phy_impl->an_advertising = axgbe_phy_an_advertising; 2304a5c72737SRavi Kumar phy_impl->an_outcome = axgbe_phy_an_outcome; 230500072056SRavi Kumar 230600072056SRavi Kumar phy_impl->an_pre = axgbe_phy_an_pre; 230700072056SRavi Kumar phy_impl->an_post = axgbe_phy_an_post; 230800072056SRavi Kumar 230900072056SRavi Kumar phy_impl->kr_training_pre = axgbe_phy_kr_training_pre; 231000072056SRavi Kumar phy_impl->kr_training_post = axgbe_phy_kr_training_post; 23114ac7516bSRavi Kumar } 2312