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 104ac7516bSRavi Kumar #define AXGBE_PHY_PORT_SPEED_100 BIT(0) 114ac7516bSRavi Kumar #define AXGBE_PHY_PORT_SPEED_1000 BIT(1) 124ac7516bSRavi Kumar #define AXGBE_PHY_PORT_SPEED_2500 BIT(2) 134ac7516bSRavi Kumar #define AXGBE_PHY_PORT_SPEED_10000 BIT(3) 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, 494ac7516bSRavi Kumar AXGBE_PORT_MODE_MAX, 504ac7516bSRavi Kumar }; 514ac7516bSRavi Kumar 524ac7516bSRavi Kumar enum axgbe_conn_type { 534ac7516bSRavi Kumar AXGBE_CONN_TYPE_NONE = 0, 544ac7516bSRavi Kumar AXGBE_CONN_TYPE_SFP, 554ac7516bSRavi Kumar AXGBE_CONN_TYPE_MDIO, 564ac7516bSRavi Kumar AXGBE_CONN_TYPE_RSVD1, 574ac7516bSRavi Kumar AXGBE_CONN_TYPE_BACKPLANE, 584ac7516bSRavi Kumar AXGBE_CONN_TYPE_MAX, 594ac7516bSRavi Kumar }; 604ac7516bSRavi Kumar 614ac7516bSRavi Kumar /* SFP/SFP+ related definitions */ 624ac7516bSRavi Kumar enum axgbe_sfp_comm { 634ac7516bSRavi Kumar AXGBE_SFP_COMM_DIRECT = 0, 644ac7516bSRavi Kumar AXGBE_SFP_COMM_PCA9545, 654ac7516bSRavi Kumar }; 664ac7516bSRavi Kumar 674ac7516bSRavi Kumar enum axgbe_sfp_cable { 684ac7516bSRavi Kumar AXGBE_SFP_CABLE_UNKNOWN = 0, 694ac7516bSRavi Kumar AXGBE_SFP_CABLE_ACTIVE, 704ac7516bSRavi Kumar AXGBE_SFP_CABLE_PASSIVE, 714ac7516bSRavi Kumar }; 724ac7516bSRavi Kumar 734ac7516bSRavi Kumar enum axgbe_sfp_base { 744ac7516bSRavi Kumar AXGBE_SFP_BASE_UNKNOWN = 0, 754ac7516bSRavi Kumar AXGBE_SFP_BASE_1000_T, 764ac7516bSRavi Kumar AXGBE_SFP_BASE_1000_SX, 774ac7516bSRavi Kumar AXGBE_SFP_BASE_1000_LX, 784ac7516bSRavi Kumar AXGBE_SFP_BASE_1000_CX, 794ac7516bSRavi Kumar AXGBE_SFP_BASE_10000_SR, 804ac7516bSRavi Kumar AXGBE_SFP_BASE_10000_LR, 814ac7516bSRavi Kumar AXGBE_SFP_BASE_10000_LRM, 824ac7516bSRavi Kumar AXGBE_SFP_BASE_10000_ER, 834ac7516bSRavi Kumar AXGBE_SFP_BASE_10000_CR, 844ac7516bSRavi Kumar }; 854ac7516bSRavi Kumar 864ac7516bSRavi Kumar enum axgbe_sfp_speed { 874ac7516bSRavi Kumar AXGBE_SFP_SPEED_UNKNOWN = 0, 884ac7516bSRavi Kumar AXGBE_SFP_SPEED_100_1000, 894ac7516bSRavi Kumar AXGBE_SFP_SPEED_1000, 904ac7516bSRavi Kumar AXGBE_SFP_SPEED_10000, 914ac7516bSRavi Kumar }; 924ac7516bSRavi Kumar 934ac7516bSRavi Kumar /* SFP Serial ID Base ID values relative to an offset of 0 */ 944ac7516bSRavi Kumar #define AXGBE_SFP_BASE_ID 0 954ac7516bSRavi Kumar #define AXGBE_SFP_ID_SFP 0x03 964ac7516bSRavi Kumar 974ac7516bSRavi Kumar #define AXGBE_SFP_BASE_EXT_ID 1 984ac7516bSRavi Kumar #define AXGBE_SFP_EXT_ID_SFP 0x04 994ac7516bSRavi Kumar 1004ac7516bSRavi Kumar #define AXGBE_SFP_BASE_10GBE_CC 3 1014ac7516bSRavi Kumar #define AXGBE_SFP_BASE_10GBE_CC_SR BIT(4) 1024ac7516bSRavi Kumar #define AXGBE_SFP_BASE_10GBE_CC_LR BIT(5) 1034ac7516bSRavi Kumar #define AXGBE_SFP_BASE_10GBE_CC_LRM BIT(6) 1044ac7516bSRavi Kumar #define AXGBE_SFP_BASE_10GBE_CC_ER BIT(7) 1054ac7516bSRavi Kumar 1064ac7516bSRavi Kumar #define AXGBE_SFP_BASE_1GBE_CC 6 1074ac7516bSRavi Kumar #define AXGBE_SFP_BASE_1GBE_CC_SX BIT(0) 1084ac7516bSRavi Kumar #define AXGBE_SFP_BASE_1GBE_CC_LX BIT(1) 1094ac7516bSRavi Kumar #define AXGBE_SFP_BASE_1GBE_CC_CX BIT(2) 1104ac7516bSRavi Kumar #define AXGBE_SFP_BASE_1GBE_CC_T BIT(3) 1114ac7516bSRavi Kumar 1124ac7516bSRavi Kumar #define AXGBE_SFP_BASE_CABLE 8 1134ac7516bSRavi Kumar #define AXGBE_SFP_BASE_CABLE_PASSIVE BIT(2) 1144ac7516bSRavi Kumar #define AXGBE_SFP_BASE_CABLE_ACTIVE BIT(3) 1154ac7516bSRavi Kumar 1164ac7516bSRavi Kumar #define AXGBE_SFP_BASE_BR 12 1174ac7516bSRavi Kumar #define AXGBE_SFP_BASE_BR_1GBE_MIN 0x0a 1184ac7516bSRavi Kumar #define AXGBE_SFP_BASE_BR_1GBE_MAX 0x0d 1194ac7516bSRavi Kumar #define AXGBE_SFP_BASE_BR_10GBE_MIN 0x64 1204ac7516bSRavi Kumar #define AXGBE_SFP_BASE_BR_10GBE_MAX 0x68 1214ac7516bSRavi Kumar 1224ac7516bSRavi Kumar #define AXGBE_SFP_BASE_CU_CABLE_LEN 18 1234ac7516bSRavi Kumar 1244ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_NAME 20 1254ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_NAME_LEN 16 1264ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_PN 40 1274ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_PN_LEN 16 1284ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_REV 56 1294ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_REV_LEN 4 1304ac7516bSRavi Kumar 1314ac7516bSRavi Kumar #define AXGBE_SFP_BASE_CC 63 1324ac7516bSRavi Kumar 1334ac7516bSRavi Kumar /* SFP Serial ID Extended ID values relative to an offset of 64 */ 1344ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_SN 4 1354ac7516bSRavi Kumar #define AXGBE_SFP_BASE_VENDOR_SN_LEN 16 1364ac7516bSRavi Kumar 1374ac7516bSRavi Kumar #define AXGBE_SFP_EXTD_DIAG 28 1384ac7516bSRavi Kumar #define AXGBE_SFP_EXTD_DIAG_ADDR_CHANGE BIT(2) 1394ac7516bSRavi Kumar 1404ac7516bSRavi Kumar #define AXGBE_SFP_EXTD_SFF_8472 30 1414ac7516bSRavi Kumar 1424ac7516bSRavi Kumar #define AXGBE_SFP_EXTD_CC 31 1434ac7516bSRavi Kumar 1444ac7516bSRavi Kumar struct axgbe_sfp_eeprom { 1454ac7516bSRavi Kumar u8 base[64]; 1464ac7516bSRavi Kumar u8 extd[32]; 1474ac7516bSRavi Kumar u8 vendor[32]; 1484ac7516bSRavi Kumar }; 1494ac7516bSRavi Kumar 1504ac7516bSRavi Kumar #define AXGBE_BEL_FUSE_VENDOR "BEL-FUSE" 1514ac7516bSRavi Kumar #define AXGBE_BEL_FUSE_PARTNO "1GBT-SFP06" 1524ac7516bSRavi Kumar 1534ac7516bSRavi Kumar struct axgbe_sfp_ascii { 1544ac7516bSRavi Kumar union { 1554ac7516bSRavi Kumar char vendor[AXGBE_SFP_BASE_VENDOR_NAME_LEN + 1]; 1564ac7516bSRavi Kumar char partno[AXGBE_SFP_BASE_VENDOR_PN_LEN + 1]; 1574ac7516bSRavi Kumar char rev[AXGBE_SFP_BASE_VENDOR_REV_LEN + 1]; 1584ac7516bSRavi Kumar char serno[AXGBE_SFP_BASE_VENDOR_SN_LEN + 1]; 1594ac7516bSRavi Kumar } u; 1604ac7516bSRavi Kumar }; 1614ac7516bSRavi Kumar 1624ac7516bSRavi Kumar /* MDIO PHY reset types */ 1634ac7516bSRavi Kumar enum axgbe_mdio_reset { 1644ac7516bSRavi Kumar AXGBE_MDIO_RESET_NONE = 0, 1654ac7516bSRavi Kumar AXGBE_MDIO_RESET_I2C_GPIO, 1664ac7516bSRavi Kumar AXGBE_MDIO_RESET_INT_GPIO, 1674ac7516bSRavi Kumar AXGBE_MDIO_RESET_MAX, 1684ac7516bSRavi Kumar }; 1694ac7516bSRavi Kumar 1704ac7516bSRavi Kumar /* Re-driver related definitions */ 1714ac7516bSRavi Kumar enum axgbe_phy_redrv_if { 1724ac7516bSRavi Kumar AXGBE_PHY_REDRV_IF_MDIO = 0, 1734ac7516bSRavi Kumar AXGBE_PHY_REDRV_IF_I2C, 1744ac7516bSRavi Kumar AXGBE_PHY_REDRV_IF_MAX, 1754ac7516bSRavi Kumar }; 1764ac7516bSRavi Kumar 1774ac7516bSRavi Kumar enum axgbe_phy_redrv_model { 1784ac7516bSRavi Kumar AXGBE_PHY_REDRV_MODEL_4223 = 0, 1794ac7516bSRavi Kumar AXGBE_PHY_REDRV_MODEL_4227, 1804ac7516bSRavi Kumar AXGBE_PHY_REDRV_MODEL_MAX, 1814ac7516bSRavi Kumar }; 1824ac7516bSRavi Kumar 1834ac7516bSRavi Kumar enum axgbe_phy_redrv_mode { 1844ac7516bSRavi Kumar AXGBE_PHY_REDRV_MODE_CX = 5, 1854ac7516bSRavi Kumar AXGBE_PHY_REDRV_MODE_SR = 9, 1864ac7516bSRavi Kumar }; 1874ac7516bSRavi Kumar 1884ac7516bSRavi Kumar #define AXGBE_PHY_REDRV_MODE_REG 0x12b0 1894ac7516bSRavi Kumar 1904ac7516bSRavi Kumar /* PHY related configuration information */ 1914ac7516bSRavi Kumar struct axgbe_phy_data { 1924ac7516bSRavi Kumar enum axgbe_port_mode port_mode; 1934ac7516bSRavi Kumar 1944ac7516bSRavi Kumar unsigned int port_id; 1954ac7516bSRavi Kumar 1964ac7516bSRavi Kumar unsigned int port_speeds; 1974ac7516bSRavi Kumar 1984ac7516bSRavi Kumar enum axgbe_conn_type conn_type; 1994ac7516bSRavi Kumar 2004ac7516bSRavi Kumar enum axgbe_mode cur_mode; 2014ac7516bSRavi Kumar enum axgbe_mode start_mode; 2024ac7516bSRavi Kumar 2034ac7516bSRavi Kumar unsigned int rrc_count; 2044ac7516bSRavi Kumar 2054ac7516bSRavi Kumar unsigned int mdio_addr; 2064ac7516bSRavi Kumar 2074ac7516bSRavi Kumar unsigned int comm_owned; 2084ac7516bSRavi Kumar 2094ac7516bSRavi Kumar /* SFP Support */ 2104ac7516bSRavi Kumar enum axgbe_sfp_comm sfp_comm; 2114ac7516bSRavi Kumar unsigned int sfp_mux_address; 2124ac7516bSRavi Kumar unsigned int sfp_mux_channel; 2134ac7516bSRavi Kumar 2144ac7516bSRavi Kumar unsigned int sfp_gpio_address; 2154ac7516bSRavi Kumar unsigned int sfp_gpio_mask; 2164ac7516bSRavi Kumar unsigned int sfp_gpio_rx_los; 2174ac7516bSRavi Kumar unsigned int sfp_gpio_tx_fault; 2184ac7516bSRavi Kumar unsigned int sfp_gpio_mod_absent; 2194ac7516bSRavi Kumar unsigned int sfp_gpio_rate_select; 2204ac7516bSRavi Kumar 2214ac7516bSRavi Kumar unsigned int sfp_rx_los; 2224ac7516bSRavi Kumar unsigned int sfp_tx_fault; 2234ac7516bSRavi Kumar unsigned int sfp_mod_absent; 2244ac7516bSRavi Kumar unsigned int sfp_diags; 2254ac7516bSRavi Kumar unsigned int sfp_changed; 2264ac7516bSRavi Kumar unsigned int sfp_phy_avail; 2274ac7516bSRavi Kumar unsigned int sfp_cable_len; 2284ac7516bSRavi Kumar enum axgbe_sfp_base sfp_base; 2294ac7516bSRavi Kumar enum axgbe_sfp_cable sfp_cable; 2304ac7516bSRavi Kumar enum axgbe_sfp_speed sfp_speed; 2314ac7516bSRavi Kumar struct axgbe_sfp_eeprom sfp_eeprom; 2324ac7516bSRavi Kumar 2334ac7516bSRavi Kumar /* External PHY support */ 2344ac7516bSRavi Kumar enum axgbe_mdio_mode phydev_mode; 2354ac7516bSRavi Kumar enum axgbe_mdio_reset mdio_reset; 2364ac7516bSRavi Kumar unsigned int mdio_reset_addr; 2374ac7516bSRavi Kumar unsigned int mdio_reset_gpio; 2384ac7516bSRavi Kumar 2394ac7516bSRavi Kumar /* Re-driver support */ 2404ac7516bSRavi Kumar unsigned int redrv; 2414ac7516bSRavi Kumar unsigned int redrv_if; 2424ac7516bSRavi Kumar unsigned int redrv_addr; 2434ac7516bSRavi Kumar unsigned int redrv_lane; 2444ac7516bSRavi Kumar unsigned int redrv_model; 24500072056SRavi Kumar 24600072056SRavi Kumar /* KR AN support */ 24700072056SRavi Kumar unsigned int phy_cdr_notrack; 24800072056SRavi Kumar unsigned int phy_cdr_delay; 2494ac7516bSRavi Kumar }; 2504ac7516bSRavi Kumar 251a5c72737SRavi Kumar static enum axgbe_an_mode axgbe_phy_an_mode(struct axgbe_port *pdata); 252a5c72737SRavi Kumar 253a5c72737SRavi Kumar static int axgbe_phy_i2c_xfer(struct axgbe_port *pdata, 254a5c72737SRavi Kumar struct axgbe_i2c_op *i2c_op) 255a5c72737SRavi Kumar { 256a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 257a5c72737SRavi Kumar 258a5c72737SRavi Kumar /* Be sure we own the bus */ 259a5c72737SRavi Kumar if (!phy_data->comm_owned) 260a5c72737SRavi Kumar return -EIO; 261a5c72737SRavi Kumar 262a5c72737SRavi Kumar return pdata->i2c_if.i2c_xfer(pdata, i2c_op); 263a5c72737SRavi Kumar } 264a5c72737SRavi Kumar 265a5c72737SRavi Kumar static int axgbe_phy_redrv_write(struct axgbe_port *pdata, unsigned int reg, 266a5c72737SRavi Kumar unsigned int val) 267a5c72737SRavi Kumar { 268a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 269a5c72737SRavi Kumar struct axgbe_i2c_op i2c_op; 270a5c72737SRavi Kumar uint16_t *redrv_val; 271a5c72737SRavi Kumar u8 redrv_data[5], csum; 272a5c72737SRavi Kumar unsigned int i, retry; 273a5c72737SRavi Kumar int ret; 274a5c72737SRavi Kumar 275a5c72737SRavi Kumar /* High byte of register contains read/write indicator */ 276a5c72737SRavi Kumar redrv_data[0] = ((reg >> 8) & 0xff) << 1; 277a5c72737SRavi Kumar redrv_data[1] = reg & 0xff; 278a5c72737SRavi Kumar redrv_val = (uint16_t *)&redrv_data[2]; 279a5c72737SRavi Kumar *redrv_val = rte_cpu_to_be_16(val); 280a5c72737SRavi Kumar 281a5c72737SRavi Kumar /* Calculate 1 byte checksum */ 282a5c72737SRavi Kumar csum = 0; 283a5c72737SRavi Kumar for (i = 0; i < 4; i++) { 284a5c72737SRavi Kumar csum += redrv_data[i]; 285a5c72737SRavi Kumar if (redrv_data[i] > csum) 286a5c72737SRavi Kumar csum++; 287a5c72737SRavi Kumar } 288a5c72737SRavi Kumar redrv_data[4] = ~csum; 289a5c72737SRavi Kumar 290a5c72737SRavi Kumar retry = 1; 291a5c72737SRavi Kumar again1: 292a5c72737SRavi Kumar i2c_op.cmd = AXGBE_I2C_CMD_WRITE; 293a5c72737SRavi Kumar i2c_op.target = phy_data->redrv_addr; 294a5c72737SRavi Kumar i2c_op.len = sizeof(redrv_data); 295a5c72737SRavi Kumar i2c_op.buf = redrv_data; 296a5c72737SRavi Kumar ret = axgbe_phy_i2c_xfer(pdata, &i2c_op); 297a5c72737SRavi Kumar if (ret) { 298a5c72737SRavi Kumar if ((ret == -EAGAIN) && retry--) 299a5c72737SRavi Kumar goto again1; 300a5c72737SRavi Kumar 301a5c72737SRavi Kumar return ret; 302a5c72737SRavi Kumar } 303a5c72737SRavi Kumar 304a5c72737SRavi Kumar retry = 1; 305a5c72737SRavi Kumar again2: 306a5c72737SRavi Kumar i2c_op.cmd = AXGBE_I2C_CMD_READ; 307a5c72737SRavi Kumar i2c_op.target = phy_data->redrv_addr; 308a5c72737SRavi Kumar i2c_op.len = 1; 309a5c72737SRavi Kumar i2c_op.buf = redrv_data; 310a5c72737SRavi Kumar ret = axgbe_phy_i2c_xfer(pdata, &i2c_op); 311a5c72737SRavi Kumar if (ret) { 312a5c72737SRavi Kumar if ((ret == -EAGAIN) && retry--) 313a5c72737SRavi Kumar goto again2; 314a5c72737SRavi Kumar 315a5c72737SRavi Kumar return ret; 316a5c72737SRavi Kumar } 317a5c72737SRavi Kumar 318a5c72737SRavi Kumar if (redrv_data[0] != 0xff) { 319a5c72737SRavi Kumar PMD_DRV_LOG(ERR, "Redriver write checksum error\n"); 320a5c72737SRavi Kumar ret = -EIO; 321a5c72737SRavi Kumar } 322a5c72737SRavi Kumar 323a5c72737SRavi Kumar return ret; 324a5c72737SRavi Kumar } 325a5c72737SRavi Kumar 326a5c72737SRavi Kumar static int axgbe_phy_i2c_read(struct axgbe_port *pdata, unsigned int target, 327a5c72737SRavi Kumar void *reg, unsigned int reg_len, 328a5c72737SRavi Kumar void *val, unsigned int val_len) 329a5c72737SRavi Kumar { 330a5c72737SRavi Kumar struct axgbe_i2c_op i2c_op; 331a5c72737SRavi Kumar int retry, ret; 332a5c72737SRavi Kumar 333a5c72737SRavi Kumar retry = 1; 334a5c72737SRavi Kumar again1: 335a5c72737SRavi Kumar /* Set the specified register to read */ 336a5c72737SRavi Kumar i2c_op.cmd = AXGBE_I2C_CMD_WRITE; 337a5c72737SRavi Kumar i2c_op.target = target; 338a5c72737SRavi Kumar i2c_op.len = reg_len; 339a5c72737SRavi Kumar i2c_op.buf = reg; 340a5c72737SRavi Kumar ret = axgbe_phy_i2c_xfer(pdata, &i2c_op); 341a5c72737SRavi Kumar if (ret) { 342a5c72737SRavi Kumar if ((ret == -EAGAIN) && retry--) 343a5c72737SRavi Kumar goto again1; 344a5c72737SRavi Kumar 345a5c72737SRavi Kumar return ret; 346a5c72737SRavi Kumar } 347a5c72737SRavi Kumar 348a5c72737SRavi Kumar retry = 1; 349a5c72737SRavi Kumar again2: 350a5c72737SRavi Kumar /* Read the specfied register */ 351a5c72737SRavi Kumar i2c_op.cmd = AXGBE_I2C_CMD_READ; 352a5c72737SRavi Kumar i2c_op.target = target; 353a5c72737SRavi Kumar i2c_op.len = val_len; 354a5c72737SRavi Kumar i2c_op.buf = val; 355a5c72737SRavi Kumar ret = axgbe_phy_i2c_xfer(pdata, &i2c_op); 356a5c72737SRavi Kumar if ((ret == -EAGAIN) && retry--) 357a5c72737SRavi Kumar goto again2; 358a5c72737SRavi Kumar 359a5c72737SRavi Kumar return ret; 360a5c72737SRavi Kumar } 361a5c72737SRavi Kumar 362a5c72737SRavi Kumar static int axgbe_phy_sfp_put_mux(struct axgbe_port *pdata) 363a5c72737SRavi Kumar { 364a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 365a5c72737SRavi Kumar struct axgbe_i2c_op i2c_op; 366a5c72737SRavi Kumar uint8_t mux_channel; 367a5c72737SRavi Kumar 368a5c72737SRavi Kumar if (phy_data->sfp_comm == AXGBE_SFP_COMM_DIRECT) 369a5c72737SRavi Kumar return 0; 370a5c72737SRavi Kumar 371a5c72737SRavi Kumar /* Select no mux channels */ 372a5c72737SRavi Kumar mux_channel = 0; 373a5c72737SRavi Kumar i2c_op.cmd = AXGBE_I2C_CMD_WRITE; 374a5c72737SRavi Kumar i2c_op.target = phy_data->sfp_mux_address; 375a5c72737SRavi Kumar i2c_op.len = sizeof(mux_channel); 376a5c72737SRavi Kumar i2c_op.buf = &mux_channel; 377a5c72737SRavi Kumar 378a5c72737SRavi Kumar return axgbe_phy_i2c_xfer(pdata, &i2c_op); 379a5c72737SRavi Kumar } 380a5c72737SRavi Kumar 381a5c72737SRavi Kumar static int axgbe_phy_sfp_get_mux(struct axgbe_port *pdata) 382a5c72737SRavi Kumar { 383a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 384a5c72737SRavi Kumar struct axgbe_i2c_op i2c_op; 385a5c72737SRavi Kumar u8 mux_channel; 386a5c72737SRavi Kumar 387a5c72737SRavi Kumar if (phy_data->sfp_comm == AXGBE_SFP_COMM_DIRECT) 388a5c72737SRavi Kumar return 0; 389a5c72737SRavi Kumar 390a5c72737SRavi Kumar /* Select desired mux channel */ 391a5c72737SRavi Kumar mux_channel = 1 << phy_data->sfp_mux_channel; 392a5c72737SRavi Kumar i2c_op.cmd = AXGBE_I2C_CMD_WRITE; 393a5c72737SRavi Kumar i2c_op.target = phy_data->sfp_mux_address; 394a5c72737SRavi Kumar i2c_op.len = sizeof(mux_channel); 395a5c72737SRavi Kumar i2c_op.buf = &mux_channel; 396a5c72737SRavi Kumar 397a5c72737SRavi Kumar return axgbe_phy_i2c_xfer(pdata, &i2c_op); 398a5c72737SRavi Kumar } 399a5c72737SRavi Kumar 400a5c72737SRavi Kumar static void axgbe_phy_put_comm_ownership(struct axgbe_port *pdata) 401a5c72737SRavi Kumar { 402a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 403a5c72737SRavi Kumar 404a5c72737SRavi Kumar phy_data->comm_owned = 0; 405a5c72737SRavi Kumar 406a5c72737SRavi Kumar pthread_mutex_unlock(&pdata->phy_mutex); 407a5c72737SRavi Kumar } 408a5c72737SRavi Kumar 409a5c72737SRavi Kumar static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata) 410a5c72737SRavi Kumar { 411a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 412a5c72737SRavi Kumar uint64_t timeout; 413a5c72737SRavi Kumar unsigned int mutex_id; 414a5c72737SRavi Kumar 415a5c72737SRavi Kumar /* The I2C and MDIO/GPIO bus is multiplexed between multiple devices, 416a5c72737SRavi Kumar * the driver needs to take the software mutex and then the hardware 417a5c72737SRavi Kumar * mutexes before being able to use the busses. 418a5c72737SRavi Kumar */ 419a5c72737SRavi Kumar pthread_mutex_lock(&pdata->phy_mutex); 420a5c72737SRavi Kumar 421c8c2296bSPallantla Poornima if (phy_data->comm_owned) 422c8c2296bSPallantla Poornima return 0; 423c8c2296bSPallantla Poornima 424a5c72737SRavi Kumar /* Clear the mutexes */ 425a5c72737SRavi Kumar XP_IOWRITE(pdata, XP_I2C_MUTEX, AXGBE_MUTEX_RELEASE); 426a5c72737SRavi Kumar XP_IOWRITE(pdata, XP_MDIO_MUTEX, AXGBE_MUTEX_RELEASE); 427a5c72737SRavi Kumar 428a5c72737SRavi Kumar /* Mutex formats are the same for I2C and MDIO/GPIO */ 429a5c72737SRavi Kumar mutex_id = 0; 430a5c72737SRavi Kumar XP_SET_BITS(mutex_id, XP_I2C_MUTEX, ID, phy_data->port_id); 431a5c72737SRavi Kumar XP_SET_BITS(mutex_id, XP_I2C_MUTEX, ACTIVE, 1); 432a5c72737SRavi Kumar 433a5c72737SRavi Kumar timeout = rte_get_timer_cycles() + (rte_get_timer_hz() * 5); 434a5c72737SRavi Kumar while (time_before(rte_get_timer_cycles(), timeout)) { 435a5c72737SRavi Kumar /* Must be all zeroes in order to obtain the mutex */ 436a5c72737SRavi Kumar if (XP_IOREAD(pdata, XP_I2C_MUTEX) || 437a5c72737SRavi Kumar XP_IOREAD(pdata, XP_MDIO_MUTEX)) { 438a5c72737SRavi Kumar rte_delay_us(100); 439a5c72737SRavi Kumar continue; 440a5c72737SRavi Kumar } 441a5c72737SRavi Kumar 442a5c72737SRavi Kumar /* Obtain the mutex */ 443a5c72737SRavi Kumar XP_IOWRITE(pdata, XP_I2C_MUTEX, mutex_id); 444a5c72737SRavi Kumar XP_IOWRITE(pdata, XP_MDIO_MUTEX, mutex_id); 445a5c72737SRavi Kumar 446a5c72737SRavi Kumar phy_data->comm_owned = 1; 447a5c72737SRavi Kumar return 0; 448a5c72737SRavi Kumar } 449a5c72737SRavi Kumar 450a5c72737SRavi Kumar pthread_mutex_unlock(&pdata->phy_mutex); 451a5c72737SRavi Kumar 452a5c72737SRavi Kumar PMD_DRV_LOG(ERR, "unable to obtain hardware mutexes\n"); 453a5c72737SRavi Kumar 454a5c72737SRavi Kumar return -ETIMEDOUT; 455a5c72737SRavi Kumar } 456a5c72737SRavi Kumar 457a5c72737SRavi Kumar static void axgbe_phy_sfp_phy_settings(struct axgbe_port *pdata) 458a5c72737SRavi Kumar { 459a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 460a5c72737SRavi Kumar 461a5c72737SRavi Kumar if (phy_data->sfp_mod_absent) { 462a5c72737SRavi Kumar pdata->phy.speed = SPEED_UNKNOWN; 463a5c72737SRavi Kumar pdata->phy.duplex = DUPLEX_UNKNOWN; 464a5c72737SRavi Kumar pdata->phy.autoneg = AUTONEG_ENABLE; 465a5c72737SRavi Kumar pdata->phy.advertising = pdata->phy.supported; 466a5c72737SRavi Kumar } 467a5c72737SRavi Kumar 468a5c72737SRavi Kumar pdata->phy.advertising &= ~ADVERTISED_Autoneg; 469a5c72737SRavi Kumar pdata->phy.advertising &= ~ADVERTISED_TP; 470a5c72737SRavi Kumar pdata->phy.advertising &= ~ADVERTISED_FIBRE; 471a5c72737SRavi Kumar pdata->phy.advertising &= ~ADVERTISED_100baseT_Full; 472a5c72737SRavi Kumar pdata->phy.advertising &= ~ADVERTISED_1000baseT_Full; 473a5c72737SRavi Kumar pdata->phy.advertising &= ~ADVERTISED_10000baseT_Full; 474a5c72737SRavi Kumar pdata->phy.advertising &= ~ADVERTISED_10000baseR_FEC; 475a5c72737SRavi Kumar 476a5c72737SRavi Kumar switch (phy_data->sfp_base) { 477a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_T: 478a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_SX: 479a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_LX: 480a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_CX: 481a5c72737SRavi Kumar pdata->phy.speed = SPEED_UNKNOWN; 482a5c72737SRavi Kumar pdata->phy.duplex = DUPLEX_UNKNOWN; 483a5c72737SRavi Kumar pdata->phy.autoneg = AUTONEG_ENABLE; 484a5c72737SRavi Kumar pdata->phy.advertising |= ADVERTISED_Autoneg; 485a5c72737SRavi Kumar break; 486a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_SR: 487a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_LR: 488a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_LRM: 489a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_ER: 490a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_CR: 491a5c72737SRavi Kumar default: 492a5c72737SRavi Kumar pdata->phy.speed = SPEED_10000; 493a5c72737SRavi Kumar pdata->phy.duplex = DUPLEX_FULL; 494a5c72737SRavi Kumar pdata->phy.autoneg = AUTONEG_DISABLE; 495a5c72737SRavi Kumar break; 496a5c72737SRavi Kumar } 497a5c72737SRavi Kumar 498a5c72737SRavi Kumar switch (phy_data->sfp_base) { 499a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_T: 500a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_CX: 501a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_CR: 502a5c72737SRavi Kumar pdata->phy.advertising |= ADVERTISED_TP; 503a5c72737SRavi Kumar break; 504a5c72737SRavi Kumar default: 505a5c72737SRavi Kumar pdata->phy.advertising |= ADVERTISED_FIBRE; 506a5c72737SRavi Kumar } 507a5c72737SRavi Kumar 508a5c72737SRavi Kumar switch (phy_data->sfp_speed) { 509a5c72737SRavi Kumar case AXGBE_SFP_SPEED_100_1000: 510a5c72737SRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) 511a5c72737SRavi Kumar pdata->phy.advertising |= ADVERTISED_100baseT_Full; 512a5c72737SRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) 513a5c72737SRavi Kumar pdata->phy.advertising |= ADVERTISED_1000baseT_Full; 514a5c72737SRavi Kumar break; 515a5c72737SRavi Kumar case AXGBE_SFP_SPEED_1000: 516a5c72737SRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) 517a5c72737SRavi Kumar pdata->phy.advertising |= ADVERTISED_1000baseT_Full; 518a5c72737SRavi Kumar break; 519a5c72737SRavi Kumar case AXGBE_SFP_SPEED_10000: 520a5c72737SRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) 521a5c72737SRavi Kumar pdata->phy.advertising |= ADVERTISED_10000baseT_Full; 522a5c72737SRavi Kumar break; 523a5c72737SRavi Kumar default: 524a5c72737SRavi Kumar /* Choose the fastest supported speed */ 525a5c72737SRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) 526a5c72737SRavi Kumar pdata->phy.advertising |= ADVERTISED_10000baseT_Full; 527a5c72737SRavi Kumar else if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) 528a5c72737SRavi Kumar pdata->phy.advertising |= ADVERTISED_1000baseT_Full; 529a5c72737SRavi Kumar else if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) 530a5c72737SRavi Kumar pdata->phy.advertising |= ADVERTISED_100baseT_Full; 531a5c72737SRavi Kumar } 532a5c72737SRavi Kumar } 533a5c72737SRavi Kumar 534a5c72737SRavi Kumar static bool axgbe_phy_sfp_bit_rate(struct axgbe_sfp_eeprom *sfp_eeprom, 535a5c72737SRavi Kumar enum axgbe_sfp_speed sfp_speed) 536a5c72737SRavi Kumar { 537a5c72737SRavi Kumar u8 *sfp_base, min, max; 538a5c72737SRavi Kumar 539a5c72737SRavi Kumar sfp_base = sfp_eeprom->base; 540a5c72737SRavi Kumar 541a5c72737SRavi Kumar switch (sfp_speed) { 542a5c72737SRavi Kumar case AXGBE_SFP_SPEED_1000: 543a5c72737SRavi Kumar min = AXGBE_SFP_BASE_BR_1GBE_MIN; 544a5c72737SRavi Kumar max = AXGBE_SFP_BASE_BR_1GBE_MAX; 545a5c72737SRavi Kumar break; 546a5c72737SRavi Kumar case AXGBE_SFP_SPEED_10000: 547a5c72737SRavi Kumar min = AXGBE_SFP_BASE_BR_10GBE_MIN; 548a5c72737SRavi Kumar max = AXGBE_SFP_BASE_BR_10GBE_MAX; 549a5c72737SRavi Kumar break; 550a5c72737SRavi Kumar default: 551a5c72737SRavi Kumar return false; 552a5c72737SRavi Kumar } 553a5c72737SRavi Kumar 554a5c72737SRavi Kumar return ((sfp_base[AXGBE_SFP_BASE_BR] >= min) && 555a5c72737SRavi Kumar (sfp_base[AXGBE_SFP_BASE_BR] <= max)); 556a5c72737SRavi Kumar } 557a5c72737SRavi Kumar 558a5c72737SRavi Kumar static void axgbe_phy_sfp_external_phy(struct axgbe_port *pdata) 559a5c72737SRavi Kumar { 560a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 561a5c72737SRavi Kumar 562a5c72737SRavi Kumar if (!phy_data->sfp_changed) 563a5c72737SRavi Kumar return; 564a5c72737SRavi Kumar 565a5c72737SRavi Kumar phy_data->sfp_phy_avail = 0; 566a5c72737SRavi Kumar 567a5c72737SRavi Kumar if (phy_data->sfp_base != AXGBE_SFP_BASE_1000_T) 568a5c72737SRavi Kumar return; 569a5c72737SRavi Kumar } 570a5c72737SRavi Kumar 571a5c72737SRavi Kumar static bool axgbe_phy_belfuse_parse_quirks(struct axgbe_port *pdata) 572a5c72737SRavi Kumar { 573a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 574a5c72737SRavi Kumar struct axgbe_sfp_eeprom *sfp_eeprom = &phy_data->sfp_eeprom; 575a5c72737SRavi Kumar 576a5c72737SRavi Kumar if (memcmp(&sfp_eeprom->base[AXGBE_SFP_BASE_VENDOR_NAME], 57727578231SAndy Green AXGBE_BEL_FUSE_VENDOR, strlen(AXGBE_BEL_FUSE_VENDOR))) 578a5c72737SRavi Kumar return false; 579a5c72737SRavi Kumar 580a5c72737SRavi Kumar if (!memcmp(&sfp_eeprom->base[AXGBE_SFP_BASE_VENDOR_PN], 58127578231SAndy Green AXGBE_BEL_FUSE_PARTNO, strlen(AXGBE_BEL_FUSE_PARTNO))) { 582a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_1000_SX; 583a5c72737SRavi Kumar phy_data->sfp_cable = AXGBE_SFP_CABLE_ACTIVE; 584a5c72737SRavi Kumar phy_data->sfp_speed = AXGBE_SFP_SPEED_1000; 585a5c72737SRavi Kumar return true; 586a5c72737SRavi Kumar } 587a5c72737SRavi Kumar 588a5c72737SRavi Kumar return false; 589a5c72737SRavi Kumar } 590a5c72737SRavi Kumar 591a5c72737SRavi Kumar static bool axgbe_phy_sfp_parse_quirks(struct axgbe_port *pdata) 592a5c72737SRavi Kumar { 593a5c72737SRavi Kumar if (axgbe_phy_belfuse_parse_quirks(pdata)) 594a5c72737SRavi Kumar return true; 595a5c72737SRavi Kumar 596a5c72737SRavi Kumar return false; 597a5c72737SRavi Kumar } 598a5c72737SRavi Kumar 599a5c72737SRavi Kumar static void axgbe_phy_sfp_parse_eeprom(struct axgbe_port *pdata) 600a5c72737SRavi Kumar { 601a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 602a5c72737SRavi Kumar struct axgbe_sfp_eeprom *sfp_eeprom = &phy_data->sfp_eeprom; 603a5c72737SRavi Kumar uint8_t *sfp_base; 604a5c72737SRavi Kumar 605a5c72737SRavi Kumar sfp_base = sfp_eeprom->base; 606a5c72737SRavi Kumar 607a5c72737SRavi Kumar if (sfp_base[AXGBE_SFP_BASE_ID] != AXGBE_SFP_ID_SFP) 608a5c72737SRavi Kumar return; 609a5c72737SRavi Kumar 610a5c72737SRavi Kumar if (sfp_base[AXGBE_SFP_BASE_EXT_ID] != AXGBE_SFP_EXT_ID_SFP) 611a5c72737SRavi Kumar return; 612a5c72737SRavi Kumar 613*936e294cSGirish Nandibasappa axgbe_phy_sfp_parse_quirks(pdata); 614a5c72737SRavi Kumar 615a5c72737SRavi Kumar /* Assume ACTIVE cable unless told it is PASSIVE */ 616a5c72737SRavi Kumar if (sfp_base[AXGBE_SFP_BASE_CABLE] & AXGBE_SFP_BASE_CABLE_PASSIVE) { 617a5c72737SRavi Kumar phy_data->sfp_cable = AXGBE_SFP_CABLE_PASSIVE; 618a5c72737SRavi Kumar phy_data->sfp_cable_len = sfp_base[AXGBE_SFP_BASE_CU_CABLE_LEN]; 619a5c72737SRavi Kumar } else { 620a5c72737SRavi Kumar phy_data->sfp_cable = AXGBE_SFP_CABLE_ACTIVE; 621a5c72737SRavi Kumar } 622a5c72737SRavi Kumar 623a5c72737SRavi Kumar /* Determine the type of SFP */ 624a5c72737SRavi Kumar if (sfp_base[AXGBE_SFP_BASE_10GBE_CC] & AXGBE_SFP_BASE_10GBE_CC_SR) 625a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_10000_SR; 626a5c72737SRavi Kumar else if (sfp_base[AXGBE_SFP_BASE_10GBE_CC] & AXGBE_SFP_BASE_10GBE_CC_LR) 627a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_10000_LR; 628a5c72737SRavi Kumar else if (sfp_base[AXGBE_SFP_BASE_10GBE_CC] & 629a5c72737SRavi Kumar AXGBE_SFP_BASE_10GBE_CC_LRM) 630a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_10000_LRM; 631a5c72737SRavi Kumar else if (sfp_base[AXGBE_SFP_BASE_10GBE_CC] & AXGBE_SFP_BASE_10GBE_CC_ER) 632a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_10000_ER; 633a5c72737SRavi Kumar else if (sfp_base[AXGBE_SFP_BASE_1GBE_CC] & AXGBE_SFP_BASE_1GBE_CC_SX) 634a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_1000_SX; 635a5c72737SRavi Kumar else if (sfp_base[AXGBE_SFP_BASE_1GBE_CC] & AXGBE_SFP_BASE_1GBE_CC_LX) 636a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_1000_LX; 637a5c72737SRavi Kumar else if (sfp_base[AXGBE_SFP_BASE_1GBE_CC] & AXGBE_SFP_BASE_1GBE_CC_CX) 638a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_1000_CX; 639a5c72737SRavi Kumar else if (sfp_base[AXGBE_SFP_BASE_1GBE_CC] & AXGBE_SFP_BASE_1GBE_CC_T) 640a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_1000_T; 641a5c72737SRavi Kumar else if ((phy_data->sfp_cable == AXGBE_SFP_CABLE_PASSIVE) && 642a5c72737SRavi Kumar axgbe_phy_sfp_bit_rate(sfp_eeprom, AXGBE_SFP_SPEED_10000)) 643a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_10000_CR; 644a5c72737SRavi Kumar 645a5c72737SRavi Kumar switch (phy_data->sfp_base) { 646a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_T: 647a5c72737SRavi Kumar phy_data->sfp_speed = AXGBE_SFP_SPEED_100_1000; 648a5c72737SRavi Kumar break; 649a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_SX: 650a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_LX: 651a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_CX: 652a5c72737SRavi Kumar phy_data->sfp_speed = AXGBE_SFP_SPEED_1000; 653a5c72737SRavi Kumar break; 654a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_SR: 655a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_LR: 656a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_LRM: 657a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_ER: 658a5c72737SRavi Kumar case AXGBE_SFP_BASE_10000_CR: 659a5c72737SRavi Kumar phy_data->sfp_speed = AXGBE_SFP_SPEED_10000; 660a5c72737SRavi Kumar break; 661a5c72737SRavi Kumar default: 662a5c72737SRavi Kumar break; 663a5c72737SRavi Kumar } 664a5c72737SRavi Kumar } 665a5c72737SRavi Kumar 666a5c72737SRavi Kumar static bool axgbe_phy_sfp_verify_eeprom(uint8_t cc_in, uint8_t *buf, 667a5c72737SRavi Kumar unsigned int len) 668a5c72737SRavi Kumar { 669a5c72737SRavi Kumar uint8_t cc; 670a5c72737SRavi Kumar 671a5c72737SRavi Kumar for (cc = 0; len; buf++, len--) 672a5c72737SRavi Kumar cc += *buf; 673a5c72737SRavi Kumar 674a5c72737SRavi Kumar return (cc == cc_in) ? true : false; 675a5c72737SRavi Kumar } 676a5c72737SRavi Kumar 677a5c72737SRavi Kumar static int axgbe_phy_sfp_read_eeprom(struct axgbe_port *pdata) 678a5c72737SRavi Kumar { 679a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 680a5c72737SRavi Kumar struct axgbe_sfp_eeprom sfp_eeprom; 681a5c72737SRavi Kumar uint8_t eeprom_addr; 682a5c72737SRavi Kumar int ret; 683a5c72737SRavi Kumar 684a5c72737SRavi Kumar ret = axgbe_phy_sfp_get_mux(pdata); 685a5c72737SRavi Kumar if (ret) { 686a5c72737SRavi Kumar PMD_DRV_LOG(ERR, "I2C error setting SFP MUX\n"); 687a5c72737SRavi Kumar return ret; 688a5c72737SRavi Kumar } 689a5c72737SRavi Kumar 690a5c72737SRavi Kumar /* Read the SFP serial ID eeprom */ 691a5c72737SRavi Kumar eeprom_addr = 0; 692a5c72737SRavi Kumar ret = axgbe_phy_i2c_read(pdata, AXGBE_SFP_SERIAL_ID_ADDRESS, 693a5c72737SRavi Kumar &eeprom_addr, sizeof(eeprom_addr), 694a5c72737SRavi Kumar &sfp_eeprom, sizeof(sfp_eeprom)); 695a5c72737SRavi Kumar if (ret) { 696a5c72737SRavi Kumar PMD_DRV_LOG(ERR, "I2C error reading SFP EEPROM\n"); 697a5c72737SRavi Kumar goto put; 698a5c72737SRavi Kumar } 699a5c72737SRavi Kumar 700a5c72737SRavi Kumar /* Validate the contents read */ 701a5c72737SRavi Kumar if (!axgbe_phy_sfp_verify_eeprom(sfp_eeprom.base[AXGBE_SFP_BASE_CC], 702a5c72737SRavi Kumar sfp_eeprom.base, 703a5c72737SRavi Kumar sizeof(sfp_eeprom.base) - 1)) { 704a5c72737SRavi Kumar ret = -EINVAL; 705a5c72737SRavi Kumar goto put; 706a5c72737SRavi Kumar } 707a5c72737SRavi Kumar 708a5c72737SRavi Kumar if (!axgbe_phy_sfp_verify_eeprom(sfp_eeprom.extd[AXGBE_SFP_EXTD_CC], 709a5c72737SRavi Kumar sfp_eeprom.extd, 710a5c72737SRavi Kumar sizeof(sfp_eeprom.extd) - 1)) { 711a5c72737SRavi Kumar ret = -EINVAL; 712a5c72737SRavi Kumar goto put; 713a5c72737SRavi Kumar } 714a5c72737SRavi Kumar 715a5c72737SRavi Kumar /* Check for an added or changed SFP */ 716a5c72737SRavi Kumar if (memcmp(&phy_data->sfp_eeprom, &sfp_eeprom, sizeof(sfp_eeprom))) { 717a5c72737SRavi Kumar phy_data->sfp_changed = 1; 718a5c72737SRavi Kumar memcpy(&phy_data->sfp_eeprom, &sfp_eeprom, sizeof(sfp_eeprom)); 719a5c72737SRavi Kumar 720a5c72737SRavi Kumar if (sfp_eeprom.extd[AXGBE_SFP_EXTD_SFF_8472]) { 721a5c72737SRavi Kumar uint8_t diag_type; 722a5c72737SRavi Kumar diag_type = sfp_eeprom.extd[AXGBE_SFP_EXTD_DIAG]; 723a5c72737SRavi Kumar 724a5c72737SRavi Kumar if (!(diag_type & AXGBE_SFP_EXTD_DIAG_ADDR_CHANGE)) 725a5c72737SRavi Kumar phy_data->sfp_diags = 1; 726a5c72737SRavi Kumar } 727a5c72737SRavi Kumar } else { 728a5c72737SRavi Kumar phy_data->sfp_changed = 0; 729a5c72737SRavi Kumar } 730a5c72737SRavi Kumar 731a5c72737SRavi Kumar put: 732a5c72737SRavi Kumar axgbe_phy_sfp_put_mux(pdata); 733a5c72737SRavi Kumar 734a5c72737SRavi Kumar return ret; 735a5c72737SRavi Kumar } 736a5c72737SRavi Kumar 737a5c72737SRavi Kumar static void axgbe_phy_sfp_signals(struct axgbe_port *pdata) 738a5c72737SRavi Kumar { 739a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 740a5c72737SRavi Kumar unsigned int gpio_input; 741a5c72737SRavi Kumar u8 gpio_reg, gpio_ports[2]; 742a5c72737SRavi Kumar int ret; 743a5c72737SRavi Kumar 744a5c72737SRavi Kumar /* Read the input port registers */ 745a5c72737SRavi Kumar gpio_reg = 0; 746a5c72737SRavi Kumar ret = axgbe_phy_i2c_read(pdata, phy_data->sfp_gpio_address, 747a5c72737SRavi Kumar &gpio_reg, sizeof(gpio_reg), 748a5c72737SRavi Kumar gpio_ports, sizeof(gpio_ports)); 749a5c72737SRavi Kumar if (ret) { 750a5c72737SRavi Kumar PMD_DRV_LOG(ERR, "I2C error reading SFP GPIOs\n"); 751a5c72737SRavi Kumar return; 752a5c72737SRavi Kumar } 753a5c72737SRavi Kumar 754a5c72737SRavi Kumar gpio_input = (gpio_ports[1] << 8) | gpio_ports[0]; 755a5c72737SRavi Kumar 756a5c72737SRavi Kumar if (phy_data->sfp_gpio_mask & AXGBE_GPIO_NO_MOD_ABSENT) { 757a5c72737SRavi Kumar /* No GPIO, just assume the module is present for now */ 758a5c72737SRavi Kumar phy_data->sfp_mod_absent = 0; 759a5c72737SRavi Kumar } else { 760a5c72737SRavi Kumar if (!(gpio_input & (1 << phy_data->sfp_gpio_mod_absent))) 761a5c72737SRavi Kumar phy_data->sfp_mod_absent = 0; 762a5c72737SRavi Kumar } 763a5c72737SRavi Kumar 764a5c72737SRavi Kumar if (!(phy_data->sfp_gpio_mask & AXGBE_GPIO_NO_RX_LOS) && 765a5c72737SRavi Kumar (gpio_input & (1 << phy_data->sfp_gpio_rx_los))) 766a5c72737SRavi Kumar phy_data->sfp_rx_los = 1; 767a5c72737SRavi Kumar 768a5c72737SRavi Kumar if (!(phy_data->sfp_gpio_mask & AXGBE_GPIO_NO_TX_FAULT) && 769a5c72737SRavi Kumar (gpio_input & (1 << phy_data->sfp_gpio_tx_fault))) 770a5c72737SRavi Kumar phy_data->sfp_tx_fault = 1; 771a5c72737SRavi Kumar } 772a5c72737SRavi Kumar 773a5c72737SRavi Kumar static void axgbe_phy_sfp_mod_absent(struct axgbe_port *pdata) 774a5c72737SRavi Kumar { 775a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 776a5c72737SRavi Kumar 777a5c72737SRavi Kumar phy_data->sfp_mod_absent = 1; 778a5c72737SRavi Kumar phy_data->sfp_phy_avail = 0; 779a5c72737SRavi Kumar memset(&phy_data->sfp_eeprom, 0, sizeof(phy_data->sfp_eeprom)); 780a5c72737SRavi Kumar } 781a5c72737SRavi Kumar 782a5c72737SRavi Kumar static void axgbe_phy_sfp_reset(struct axgbe_phy_data *phy_data) 783a5c72737SRavi Kumar { 784a5c72737SRavi Kumar phy_data->sfp_rx_los = 0; 785a5c72737SRavi Kumar phy_data->sfp_tx_fault = 0; 786a5c72737SRavi Kumar phy_data->sfp_mod_absent = 1; 787a5c72737SRavi Kumar phy_data->sfp_diags = 0; 788a5c72737SRavi Kumar phy_data->sfp_base = AXGBE_SFP_BASE_UNKNOWN; 789a5c72737SRavi Kumar phy_data->sfp_cable = AXGBE_SFP_CABLE_UNKNOWN; 790a5c72737SRavi Kumar phy_data->sfp_speed = AXGBE_SFP_SPEED_UNKNOWN; 791a5c72737SRavi Kumar } 792a5c72737SRavi Kumar 793a5c72737SRavi Kumar static void axgbe_phy_sfp_detect(struct axgbe_port *pdata) 794a5c72737SRavi Kumar { 795a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 796a5c72737SRavi Kumar int ret; 797a5c72737SRavi Kumar 798a5c72737SRavi Kumar /* Reset the SFP signals and info */ 799a5c72737SRavi Kumar axgbe_phy_sfp_reset(phy_data); 800a5c72737SRavi Kumar 801a5c72737SRavi Kumar ret = axgbe_phy_get_comm_ownership(pdata); 802a5c72737SRavi Kumar if (ret) 803a5c72737SRavi Kumar return; 804a5c72737SRavi Kumar 805a5c72737SRavi Kumar /* Read the SFP signals and check for module presence */ 806a5c72737SRavi Kumar axgbe_phy_sfp_signals(pdata); 807a5c72737SRavi Kumar if (phy_data->sfp_mod_absent) { 808a5c72737SRavi Kumar axgbe_phy_sfp_mod_absent(pdata); 809a5c72737SRavi Kumar goto put; 810a5c72737SRavi Kumar } 811a5c72737SRavi Kumar 812a5c72737SRavi Kumar ret = axgbe_phy_sfp_read_eeprom(pdata); 813a5c72737SRavi Kumar if (ret) { 814a5c72737SRavi Kumar /* Treat any error as if there isn't an SFP plugged in */ 815a5c72737SRavi Kumar axgbe_phy_sfp_reset(phy_data); 816a5c72737SRavi Kumar axgbe_phy_sfp_mod_absent(pdata); 817a5c72737SRavi Kumar goto put; 818a5c72737SRavi Kumar } 819a5c72737SRavi Kumar 820a5c72737SRavi Kumar axgbe_phy_sfp_parse_eeprom(pdata); 821a5c72737SRavi Kumar axgbe_phy_sfp_external_phy(pdata); 822a5c72737SRavi Kumar 823a5c72737SRavi Kumar put: 824a5c72737SRavi Kumar axgbe_phy_sfp_phy_settings(pdata); 825a5c72737SRavi Kumar axgbe_phy_put_comm_ownership(pdata); 826a5c72737SRavi Kumar } 827a5c72737SRavi Kumar 828a5c72737SRavi Kumar static void axgbe_phy_phydev_flowctrl(struct axgbe_port *pdata) 829a5c72737SRavi Kumar { 830a5c72737SRavi Kumar pdata->phy.tx_pause = 0; 831a5c72737SRavi Kumar pdata->phy.rx_pause = 0; 832a5c72737SRavi Kumar } 833a5c72737SRavi Kumar 834a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_an73_redrv_outcome(struct axgbe_port *pdata) 835a5c72737SRavi Kumar { 836a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 837a5c72737SRavi Kumar enum axgbe_mode mode; 838a5c72737SRavi Kumar unsigned int ad_reg, lp_reg; 839a5c72737SRavi Kumar 840a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_Autoneg; 841a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_Backplane; 842a5c72737SRavi Kumar 843a5c72737SRavi Kumar /* Use external PHY to determine flow control */ 844a5c72737SRavi Kumar if (pdata->phy.pause_autoneg) 845a5c72737SRavi Kumar axgbe_phy_phydev_flowctrl(pdata); 846a5c72737SRavi Kumar 847a5c72737SRavi Kumar /* Compare Advertisement and Link Partner register 2 */ 848a5c72737SRavi Kumar ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1); 849a5c72737SRavi Kumar lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1); 850a5c72737SRavi Kumar if (lp_reg & 0x80) 851a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full; 852a5c72737SRavi Kumar if (lp_reg & 0x20) 853a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full; 854a5c72737SRavi Kumar 855a5c72737SRavi Kumar ad_reg &= lp_reg; 856a5c72737SRavi Kumar if (ad_reg & 0x80) { 857a5c72737SRavi Kumar switch (phy_data->port_mode) { 858a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 859a5c72737SRavi Kumar mode = AXGBE_MODE_KR; 860a5c72737SRavi Kumar break; 861a5c72737SRavi Kumar default: 862a5c72737SRavi Kumar mode = AXGBE_MODE_SFI; 863a5c72737SRavi Kumar break; 864a5c72737SRavi Kumar } 865a5c72737SRavi Kumar } else if (ad_reg & 0x20) { 866a5c72737SRavi Kumar switch (phy_data->port_mode) { 867a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 868a5c72737SRavi Kumar mode = AXGBE_MODE_KX_1000; 869a5c72737SRavi Kumar break; 870a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 871a5c72737SRavi Kumar mode = AXGBE_MODE_X; 872a5c72737SRavi Kumar break; 873a5c72737SRavi Kumar case AXGBE_PORT_MODE_SFP: 874a5c72737SRavi Kumar switch (phy_data->sfp_base) { 875a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_T: 876a5c72737SRavi Kumar mode = AXGBE_MODE_SGMII_1000; 877a5c72737SRavi Kumar break; 878a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_SX: 879a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_LX: 880a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_CX: 881a5c72737SRavi Kumar default: 882a5c72737SRavi Kumar mode = AXGBE_MODE_X; 883a5c72737SRavi Kumar break; 884a5c72737SRavi Kumar } 885a5c72737SRavi Kumar break; 886a5c72737SRavi Kumar default: 887a5c72737SRavi Kumar mode = AXGBE_MODE_SGMII_1000; 888a5c72737SRavi Kumar break; 889a5c72737SRavi Kumar } 890a5c72737SRavi Kumar } else { 891a5c72737SRavi Kumar mode = AXGBE_MODE_UNKNOWN; 892a5c72737SRavi Kumar } 893a5c72737SRavi Kumar 894a5c72737SRavi Kumar /* Compare Advertisement and Link Partner register 3 */ 895a5c72737SRavi Kumar ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2); 896a5c72737SRavi Kumar lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2); 897a5c72737SRavi Kumar if (lp_reg & 0xc000) 898a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC; 899a5c72737SRavi Kumar 900a5c72737SRavi Kumar return mode; 901a5c72737SRavi Kumar } 902a5c72737SRavi Kumar 903a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_an73_outcome(struct axgbe_port *pdata) 904a5c72737SRavi Kumar { 905a5c72737SRavi Kumar enum axgbe_mode mode; 906a5c72737SRavi Kumar unsigned int ad_reg, lp_reg; 907a5c72737SRavi Kumar 908a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_Autoneg; 909a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_Backplane; 910a5c72737SRavi Kumar 911a5c72737SRavi Kumar /* Compare Advertisement and Link Partner register 1 */ 912a5c72737SRavi Kumar ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE); 913a5c72737SRavi Kumar lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA); 914a5c72737SRavi Kumar if (lp_reg & 0x400) 915a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_Pause; 916a5c72737SRavi Kumar if (lp_reg & 0x800) 917a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause; 918a5c72737SRavi Kumar 919a5c72737SRavi Kumar if (pdata->phy.pause_autoneg) { 920a5c72737SRavi Kumar /* Set flow control based on auto-negotiation result */ 921a5c72737SRavi Kumar pdata->phy.tx_pause = 0; 922a5c72737SRavi Kumar pdata->phy.rx_pause = 0; 923a5c72737SRavi Kumar 924a5c72737SRavi Kumar if (ad_reg & lp_reg & 0x400) { 925a5c72737SRavi Kumar pdata->phy.tx_pause = 1; 926a5c72737SRavi Kumar pdata->phy.rx_pause = 1; 927a5c72737SRavi Kumar } else if (ad_reg & lp_reg & 0x800) { 928a5c72737SRavi Kumar if (ad_reg & 0x400) 929a5c72737SRavi Kumar pdata->phy.rx_pause = 1; 930a5c72737SRavi Kumar else if (lp_reg & 0x400) 931a5c72737SRavi Kumar pdata->phy.tx_pause = 1; 932a5c72737SRavi Kumar } 933a5c72737SRavi Kumar } 934a5c72737SRavi Kumar 935a5c72737SRavi Kumar /* Compare Advertisement and Link Partner register 2 */ 936a5c72737SRavi Kumar ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1); 937a5c72737SRavi Kumar lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1); 938a5c72737SRavi Kumar if (lp_reg & 0x80) 939a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full; 940a5c72737SRavi Kumar if (lp_reg & 0x20) 941a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full; 942a5c72737SRavi Kumar 943a5c72737SRavi Kumar ad_reg &= lp_reg; 944a5c72737SRavi Kumar if (ad_reg & 0x80) 945a5c72737SRavi Kumar mode = AXGBE_MODE_KR; 946a5c72737SRavi Kumar else if (ad_reg & 0x20) 947a5c72737SRavi Kumar mode = AXGBE_MODE_KX_1000; 948a5c72737SRavi Kumar else 949a5c72737SRavi Kumar mode = AXGBE_MODE_UNKNOWN; 950a5c72737SRavi Kumar 951a5c72737SRavi Kumar /* Compare Advertisement and Link Partner register 3 */ 952a5c72737SRavi Kumar ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2); 953a5c72737SRavi Kumar lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2); 954a5c72737SRavi Kumar if (lp_reg & 0xc000) 955a5c72737SRavi Kumar pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC; 956a5c72737SRavi Kumar 957a5c72737SRavi Kumar return mode; 958a5c72737SRavi Kumar } 959a5c72737SRavi Kumar 960a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_an_outcome(struct axgbe_port *pdata) 961a5c72737SRavi Kumar { 962a5c72737SRavi Kumar switch (pdata->an_mode) { 963a5c72737SRavi Kumar case AXGBE_AN_MODE_CL73: 964a5c72737SRavi Kumar return axgbe_phy_an73_outcome(pdata); 965a5c72737SRavi Kumar case AXGBE_AN_MODE_CL73_REDRV: 966a5c72737SRavi Kumar return axgbe_phy_an73_redrv_outcome(pdata); 967a5c72737SRavi Kumar case AXGBE_AN_MODE_CL37: 968a5c72737SRavi Kumar case AXGBE_AN_MODE_CL37_SGMII: 969a5c72737SRavi Kumar default: 970a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 971a5c72737SRavi Kumar } 972a5c72737SRavi Kumar } 973a5c72737SRavi Kumar 974a5c72737SRavi Kumar static unsigned int axgbe_phy_an_advertising(struct axgbe_port *pdata) 975a5c72737SRavi Kumar { 976a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 977a5c72737SRavi Kumar unsigned int advertising; 978a5c72737SRavi Kumar 979a5c72737SRavi Kumar /* Without a re-driver, just return current advertising */ 980a5c72737SRavi Kumar if (!phy_data->redrv) 981a5c72737SRavi Kumar return pdata->phy.advertising; 982a5c72737SRavi Kumar 983a5c72737SRavi Kumar /* With the KR re-driver we need to advertise a single speed */ 984a5c72737SRavi Kumar advertising = pdata->phy.advertising; 985a5c72737SRavi Kumar advertising &= ~ADVERTISED_1000baseKX_Full; 986a5c72737SRavi Kumar advertising &= ~ADVERTISED_10000baseKR_Full; 987a5c72737SRavi Kumar 988a5c72737SRavi Kumar switch (phy_data->port_mode) { 989a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 990a5c72737SRavi Kumar advertising |= ADVERTISED_10000baseKR_Full; 991a5c72737SRavi Kumar break; 992a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 993a5c72737SRavi Kumar advertising |= ADVERTISED_1000baseKX_Full; 994a5c72737SRavi Kumar break; 995a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 996a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 997a5c72737SRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 998a5c72737SRavi Kumar advertising |= ADVERTISED_1000baseKX_Full; 999a5c72737SRavi Kumar break; 1000a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 1001a5c72737SRavi Kumar PMD_DRV_LOG(ERR, "10GBASE_T mode is not supported\n"); 1002a5c72737SRavi Kumar break; 1003a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 1004a5c72737SRavi Kumar advertising |= ADVERTISED_10000baseKR_Full; 1005a5c72737SRavi Kumar break; 1006a5c72737SRavi Kumar case AXGBE_PORT_MODE_SFP: 1007a5c72737SRavi Kumar switch (phy_data->sfp_base) { 1008a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_T: 1009a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_SX: 1010a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_LX: 1011a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_CX: 1012a5c72737SRavi Kumar advertising |= ADVERTISED_1000baseKX_Full; 1013a5c72737SRavi Kumar break; 1014a5c72737SRavi Kumar default: 1015a5c72737SRavi Kumar advertising |= ADVERTISED_10000baseKR_Full; 1016a5c72737SRavi Kumar break; 1017a5c72737SRavi Kumar } 1018a5c72737SRavi Kumar break; 1019a5c72737SRavi Kumar default: 1020a5c72737SRavi Kumar advertising |= ADVERTISED_10000baseKR_Full; 1021a5c72737SRavi Kumar break; 1022a5c72737SRavi Kumar } 1023a5c72737SRavi Kumar 1024a5c72737SRavi Kumar return advertising; 1025a5c72737SRavi Kumar } 1026a5c72737SRavi Kumar 1027a5c72737SRavi Kumar static int axgbe_phy_an_config(struct axgbe_port *pdata __rte_unused) 1028a5c72737SRavi Kumar { 1029a5c72737SRavi Kumar return 0; 1030a5c72737SRavi Kumar /* Dummy API since there is no case to support 1031a5c72737SRavi Kumar * external phy devices registred through kerenl apis 1032a5c72737SRavi Kumar */ 1033a5c72737SRavi Kumar } 1034a5c72737SRavi Kumar 1035a5c72737SRavi Kumar static enum axgbe_an_mode axgbe_phy_an_sfp_mode(struct axgbe_phy_data *phy_data) 1036a5c72737SRavi Kumar { 1037a5c72737SRavi Kumar switch (phy_data->sfp_base) { 1038a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_T: 1039a5c72737SRavi Kumar return AXGBE_AN_MODE_CL37_SGMII; 1040a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_SX: 1041a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_LX: 1042a5c72737SRavi Kumar case AXGBE_SFP_BASE_1000_CX: 1043a5c72737SRavi Kumar return AXGBE_AN_MODE_CL37; 1044a5c72737SRavi Kumar default: 1045a5c72737SRavi Kumar return AXGBE_AN_MODE_NONE; 1046a5c72737SRavi Kumar } 1047a5c72737SRavi Kumar } 1048a5c72737SRavi Kumar 1049a5c72737SRavi Kumar static enum axgbe_an_mode axgbe_phy_an_mode(struct axgbe_port *pdata) 1050a5c72737SRavi Kumar { 1051a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1052a5c72737SRavi Kumar 1053a5c72737SRavi Kumar /* A KR re-driver will always require CL73 AN */ 1054a5c72737SRavi Kumar if (phy_data->redrv) 1055a5c72737SRavi Kumar return AXGBE_AN_MODE_CL73_REDRV; 1056a5c72737SRavi Kumar 1057a5c72737SRavi Kumar switch (phy_data->port_mode) { 1058a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 1059a5c72737SRavi Kumar return AXGBE_AN_MODE_CL73; 1060a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 1061a5c72737SRavi Kumar return AXGBE_AN_MODE_NONE; 1062a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 1063a5c72737SRavi Kumar return AXGBE_AN_MODE_CL37_SGMII; 1064a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 1065a5c72737SRavi Kumar return AXGBE_AN_MODE_CL37; 1066a5c72737SRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 1067a5c72737SRavi Kumar return AXGBE_AN_MODE_CL37_SGMII; 1068a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 1069a5c72737SRavi Kumar return AXGBE_AN_MODE_CL73; 1070a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 1071a5c72737SRavi Kumar return AXGBE_AN_MODE_NONE; 1072a5c72737SRavi Kumar case AXGBE_PORT_MODE_SFP: 1073a5c72737SRavi Kumar return axgbe_phy_an_sfp_mode(phy_data); 1074a5c72737SRavi Kumar default: 1075a5c72737SRavi Kumar return AXGBE_AN_MODE_NONE; 1076a5c72737SRavi Kumar } 1077a5c72737SRavi Kumar } 1078a5c72737SRavi Kumar 1079a5c72737SRavi Kumar static int axgbe_phy_set_redrv_mode_mdio(struct axgbe_port *pdata, 1080a5c72737SRavi Kumar enum axgbe_phy_redrv_mode mode) 1081a5c72737SRavi Kumar { 1082a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1083a5c72737SRavi Kumar u16 redrv_reg, redrv_val; 1084a5c72737SRavi Kumar 1085a5c72737SRavi Kumar redrv_reg = AXGBE_PHY_REDRV_MODE_REG + (phy_data->redrv_lane * 0x1000); 1086a5c72737SRavi Kumar redrv_val = (u16)mode; 1087a5c72737SRavi Kumar 1088a5c72737SRavi Kumar return pdata->hw_if.write_ext_mii_regs(pdata, phy_data->redrv_addr, 1089a5c72737SRavi Kumar redrv_reg, redrv_val); 1090a5c72737SRavi Kumar } 1091a5c72737SRavi Kumar 1092a5c72737SRavi Kumar static int axgbe_phy_set_redrv_mode_i2c(struct axgbe_port *pdata, 1093a5c72737SRavi Kumar enum axgbe_phy_redrv_mode mode) 1094a5c72737SRavi Kumar { 1095a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1096a5c72737SRavi Kumar unsigned int redrv_reg; 1097a5c72737SRavi Kumar int ret; 1098a5c72737SRavi Kumar 1099a5c72737SRavi Kumar /* Calculate the register to write */ 1100a5c72737SRavi Kumar redrv_reg = AXGBE_PHY_REDRV_MODE_REG + (phy_data->redrv_lane * 0x1000); 1101a5c72737SRavi Kumar 1102a5c72737SRavi Kumar ret = axgbe_phy_redrv_write(pdata, redrv_reg, mode); 1103a5c72737SRavi Kumar 1104a5c72737SRavi Kumar return ret; 1105a5c72737SRavi Kumar } 1106a5c72737SRavi Kumar 1107a5c72737SRavi Kumar static void axgbe_phy_set_redrv_mode(struct axgbe_port *pdata) 1108a5c72737SRavi Kumar { 1109a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1110a5c72737SRavi Kumar enum axgbe_phy_redrv_mode mode; 1111a5c72737SRavi Kumar int ret; 1112a5c72737SRavi Kumar 1113a5c72737SRavi Kumar if (!phy_data->redrv) 1114a5c72737SRavi Kumar return; 1115a5c72737SRavi Kumar 1116a5c72737SRavi Kumar mode = AXGBE_PHY_REDRV_MODE_CX; 1117a5c72737SRavi Kumar if ((phy_data->port_mode == AXGBE_PORT_MODE_SFP) && 1118a5c72737SRavi Kumar (phy_data->sfp_base != AXGBE_SFP_BASE_1000_CX) && 1119a5c72737SRavi Kumar (phy_data->sfp_base != AXGBE_SFP_BASE_10000_CR)) 1120a5c72737SRavi Kumar mode = AXGBE_PHY_REDRV_MODE_SR; 1121a5c72737SRavi Kumar 1122a5c72737SRavi Kumar ret = axgbe_phy_get_comm_ownership(pdata); 1123a5c72737SRavi Kumar if (ret) 1124a5c72737SRavi Kumar return; 1125a5c72737SRavi Kumar 1126a5c72737SRavi Kumar if (phy_data->redrv_if) 1127a5c72737SRavi Kumar axgbe_phy_set_redrv_mode_i2c(pdata, mode); 1128a5c72737SRavi Kumar else 1129a5c72737SRavi Kumar axgbe_phy_set_redrv_mode_mdio(pdata, mode); 1130a5c72737SRavi Kumar 1131a5c72737SRavi Kumar axgbe_phy_put_comm_ownership(pdata); 1132a5c72737SRavi Kumar } 1133a5c72737SRavi Kumar 1134a5c72737SRavi Kumar static void axgbe_phy_start_ratechange(struct axgbe_port *pdata) 1135a5c72737SRavi Kumar { 1136a5c72737SRavi Kumar if (!XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) 1137a5c72737SRavi Kumar return; 1138a5c72737SRavi Kumar } 1139a5c72737SRavi Kumar 1140a5c72737SRavi Kumar static void axgbe_phy_complete_ratechange(struct axgbe_port *pdata) 1141a5c72737SRavi Kumar { 1142a5c72737SRavi Kumar unsigned int wait; 1143a5c72737SRavi Kumar 1144a5c72737SRavi Kumar /* Wait for command to complete */ 1145a5c72737SRavi Kumar wait = AXGBE_RATECHANGE_COUNT; 1146a5c72737SRavi Kumar while (wait--) { 1147a5c72737SRavi Kumar if (!XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) 1148a5c72737SRavi Kumar return; 1149a5c72737SRavi Kumar 1150a5c72737SRavi Kumar rte_delay_us(1500); 1151a5c72737SRavi Kumar } 1152a5c72737SRavi Kumar } 1153a5c72737SRavi Kumar 1154a5c72737SRavi Kumar static void axgbe_phy_rrc(struct axgbe_port *pdata) 1155a5c72737SRavi Kumar { 1156a5c72737SRavi Kumar unsigned int s0; 1157a5c72737SRavi Kumar 1158a5c72737SRavi Kumar axgbe_phy_start_ratechange(pdata); 1159a5c72737SRavi Kumar 1160a5c72737SRavi Kumar /* Receiver Reset Cycle */ 1161a5c72737SRavi Kumar s0 = 0; 1162a5c72737SRavi Kumar XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 5); 1163a5c72737SRavi Kumar XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 0); 1164a5c72737SRavi Kumar 1165a5c72737SRavi Kumar /* Call FW to make the change */ 1166a5c72737SRavi Kumar XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0); 1167a5c72737SRavi Kumar XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0); 1168a5c72737SRavi Kumar XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1); 1169a5c72737SRavi Kumar 1170a5c72737SRavi Kumar axgbe_phy_complete_ratechange(pdata); 1171a5c72737SRavi Kumar } 1172a5c72737SRavi Kumar 1173a5c72737SRavi Kumar static void axgbe_phy_power_off(struct axgbe_port *pdata) 1174a5c72737SRavi Kumar { 1175a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1176a5c72737SRavi Kumar 1177a5c72737SRavi Kumar axgbe_phy_start_ratechange(pdata); 1178a5c72737SRavi Kumar 1179a5c72737SRavi Kumar /* Call FW to make the change */ 1180a5c72737SRavi Kumar XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, 0); 1181a5c72737SRavi Kumar XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0); 1182a5c72737SRavi Kumar XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1); 1183a5c72737SRavi Kumar axgbe_phy_complete_ratechange(pdata); 1184a5c72737SRavi Kumar phy_data->cur_mode = AXGBE_MODE_UNKNOWN; 1185a5c72737SRavi Kumar } 1186a5c72737SRavi Kumar 1187a5c72737SRavi Kumar static void axgbe_phy_sfi_mode(struct axgbe_port *pdata) 1188a5c72737SRavi Kumar { 1189a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1190a5c72737SRavi Kumar unsigned int s0; 1191a5c72737SRavi Kumar 1192a5c72737SRavi Kumar axgbe_phy_set_redrv_mode(pdata); 1193a5c72737SRavi Kumar 1194a5c72737SRavi Kumar axgbe_phy_start_ratechange(pdata); 1195a5c72737SRavi Kumar 1196a5c72737SRavi Kumar /* 10G/SFI */ 1197a5c72737SRavi Kumar s0 = 0; 1198a5c72737SRavi Kumar XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 3); 1199a5c72737SRavi Kumar if (phy_data->sfp_cable != AXGBE_SFP_CABLE_PASSIVE) { 1200a5c72737SRavi Kumar XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 0); 1201a5c72737SRavi Kumar } else { 1202a5c72737SRavi Kumar if (phy_data->sfp_cable_len <= 1) 1203a5c72737SRavi Kumar XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 1); 1204a5c72737SRavi Kumar else if (phy_data->sfp_cable_len <= 3) 1205a5c72737SRavi Kumar XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 2); 1206a5c72737SRavi Kumar else 1207a5c72737SRavi Kumar XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 3); 1208a5c72737SRavi Kumar } 1209a5c72737SRavi Kumar 1210a5c72737SRavi Kumar /* Call FW to make the change */ 1211a5c72737SRavi Kumar XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0); 1212a5c72737SRavi Kumar XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0); 1213a5c72737SRavi Kumar XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1); 1214a5c72737SRavi Kumar axgbe_phy_complete_ratechange(pdata); 1215a5c72737SRavi Kumar phy_data->cur_mode = AXGBE_MODE_SFI; 1216a5c72737SRavi Kumar } 1217a5c72737SRavi Kumar 1218a5c72737SRavi Kumar static void axgbe_phy_kr_mode(struct axgbe_port *pdata) 1219a5c72737SRavi Kumar { 1220a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1221a5c72737SRavi Kumar unsigned int s0; 1222a5c72737SRavi Kumar 1223a5c72737SRavi Kumar axgbe_phy_set_redrv_mode(pdata); 1224a5c72737SRavi Kumar 1225a5c72737SRavi Kumar axgbe_phy_start_ratechange(pdata); 1226a5c72737SRavi Kumar 1227a5c72737SRavi Kumar /* 10G/KR */ 1228a5c72737SRavi Kumar s0 = 0; 1229a5c72737SRavi Kumar XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 4); 1230a5c72737SRavi Kumar XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 0); 1231a5c72737SRavi Kumar 1232a5c72737SRavi Kumar /* Call FW to make the change */ 1233a5c72737SRavi Kumar XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0); 1234a5c72737SRavi Kumar XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0); 1235a5c72737SRavi Kumar XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1); 1236a5c72737SRavi Kumar axgbe_phy_complete_ratechange(pdata); 1237a5c72737SRavi Kumar phy_data->cur_mode = AXGBE_MODE_KR; 1238a5c72737SRavi Kumar } 1239a5c72737SRavi Kumar 1240*936e294cSGirish Nandibasappa static void axgbe_phy_kx_2500_mode(struct axgbe_port *pdata) 1241*936e294cSGirish Nandibasappa { 1242*936e294cSGirish Nandibasappa struct axgbe_phy_data *phy_data = pdata->phy_data; 1243*936e294cSGirish Nandibasappa unsigned int s0; 1244*936e294cSGirish Nandibasappa 1245*936e294cSGirish Nandibasappa axgbe_phy_set_redrv_mode(pdata); 1246*936e294cSGirish Nandibasappa /* 2.5G/KX */ 1247*936e294cSGirish Nandibasappa axgbe_phy_start_ratechange(pdata); 1248*936e294cSGirish Nandibasappa s0 = 0; 1249*936e294cSGirish Nandibasappa XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 2); 1250*936e294cSGirish Nandibasappa XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 0); 1251*936e294cSGirish Nandibasappa 1252*936e294cSGirish Nandibasappa XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0); 1253*936e294cSGirish Nandibasappa XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0); 1254*936e294cSGirish Nandibasappa 1255*936e294cSGirish Nandibasappa XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1); 1256*936e294cSGirish Nandibasappa 1257*936e294cSGirish Nandibasappa phy_data->cur_mode = AXGBE_MODE_KX_2500; 1258*936e294cSGirish Nandibasappa } 1259*936e294cSGirish Nandibasappa 1260*936e294cSGirish Nandibasappa static void axgbe_phy_sgmii_1000_mode(struct axgbe_port *pdata) 1261*936e294cSGirish Nandibasappa { 1262*936e294cSGirish Nandibasappa struct axgbe_phy_data *phy_data = pdata->phy_data; 1263*936e294cSGirish Nandibasappa unsigned int s0; 1264*936e294cSGirish Nandibasappa 1265*936e294cSGirish Nandibasappa axgbe_phy_set_redrv_mode(pdata); 1266*936e294cSGirish Nandibasappa 1267*936e294cSGirish Nandibasappa /* 1G/SGMII */ 1268*936e294cSGirish Nandibasappa axgbe_phy_start_ratechange(pdata); 1269*936e294cSGirish Nandibasappa s0 = 0; 1270*936e294cSGirish Nandibasappa XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 1); 1271*936e294cSGirish Nandibasappa XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 2); 1272*936e294cSGirish Nandibasappa 1273*936e294cSGirish Nandibasappa XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0); 1274*936e294cSGirish Nandibasappa XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0); 1275*936e294cSGirish Nandibasappa 1276*936e294cSGirish Nandibasappa XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1); 1277*936e294cSGirish Nandibasappa 1278*936e294cSGirish Nandibasappa phy_data->cur_mode = AXGBE_MODE_SGMII_1000; 1279*936e294cSGirish Nandibasappa } 1280*936e294cSGirish Nandibasappa 1281a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_cur_mode(struct axgbe_port *pdata) 1282a5c72737SRavi Kumar { 1283a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1284a5c72737SRavi Kumar 1285a5c72737SRavi Kumar return phy_data->cur_mode; 1286a5c72737SRavi Kumar } 1287a5c72737SRavi Kumar 1288a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_switch_baset_mode(struct axgbe_port *pdata) 1289a5c72737SRavi Kumar { 1290a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1291a5c72737SRavi Kumar 1292a5c72737SRavi Kumar /* No switching if not 10GBase-T */ 1293a5c72737SRavi Kumar if (phy_data->port_mode != AXGBE_PORT_MODE_10GBASE_T) 1294a5c72737SRavi Kumar return axgbe_phy_cur_mode(pdata); 1295a5c72737SRavi Kumar 1296a5c72737SRavi Kumar switch (axgbe_phy_cur_mode(pdata)) { 1297a5c72737SRavi Kumar case AXGBE_MODE_SGMII_100: 1298a5c72737SRavi Kumar case AXGBE_MODE_SGMII_1000: 1299a5c72737SRavi Kumar return AXGBE_MODE_KR; 1300a5c72737SRavi Kumar case AXGBE_MODE_KR: 1301a5c72737SRavi Kumar default: 1302a5c72737SRavi Kumar return AXGBE_MODE_SGMII_1000; 1303a5c72737SRavi Kumar } 1304a5c72737SRavi Kumar } 1305a5c72737SRavi Kumar 1306a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_switch_bp_2500_mode(struct axgbe_port *pdata 1307a5c72737SRavi Kumar __rte_unused) 1308a5c72737SRavi Kumar { 1309a5c72737SRavi Kumar return AXGBE_MODE_KX_2500; 1310a5c72737SRavi Kumar } 1311a5c72737SRavi Kumar 1312a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_switch_bp_mode(struct axgbe_port *pdata) 1313a5c72737SRavi Kumar { 1314a5c72737SRavi Kumar /* If we are in KR switch to KX, and vice-versa */ 1315a5c72737SRavi Kumar switch (axgbe_phy_cur_mode(pdata)) { 1316a5c72737SRavi Kumar case AXGBE_MODE_KX_1000: 1317a5c72737SRavi Kumar return AXGBE_MODE_KR; 1318a5c72737SRavi Kumar case AXGBE_MODE_KR: 1319a5c72737SRavi Kumar default: 1320a5c72737SRavi Kumar return AXGBE_MODE_KX_1000; 1321a5c72737SRavi Kumar } 1322a5c72737SRavi Kumar } 1323a5c72737SRavi Kumar 1324a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_switch_mode(struct axgbe_port *pdata) 1325a5c72737SRavi Kumar { 1326a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1327a5c72737SRavi Kumar 1328a5c72737SRavi Kumar switch (phy_data->port_mode) { 1329a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 1330a5c72737SRavi Kumar return axgbe_phy_switch_bp_mode(pdata); 1331a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 1332a5c72737SRavi Kumar return axgbe_phy_switch_bp_2500_mode(pdata); 1333a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 1334a5c72737SRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 1335a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 1336a5c72737SRavi Kumar return axgbe_phy_switch_baset_mode(pdata); 1337a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 1338a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 1339a5c72737SRavi Kumar case AXGBE_PORT_MODE_SFP: 1340a5c72737SRavi Kumar /* No switching, so just return current mode */ 1341a5c72737SRavi Kumar return axgbe_phy_cur_mode(pdata); 1342a5c72737SRavi Kumar default: 1343a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1344a5c72737SRavi Kumar } 1345a5c72737SRavi Kumar } 1346a5c72737SRavi Kumar 1347a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_basex_mode(struct axgbe_phy_data *phy_data 1348a5c72737SRavi Kumar __rte_unused, 1349a5c72737SRavi Kumar int speed) 1350a5c72737SRavi Kumar { 1351a5c72737SRavi Kumar switch (speed) { 1352a5c72737SRavi Kumar case SPEED_1000: 1353a5c72737SRavi Kumar return AXGBE_MODE_X; 1354a5c72737SRavi Kumar case SPEED_10000: 1355a5c72737SRavi Kumar return AXGBE_MODE_KR; 1356a5c72737SRavi Kumar default: 1357a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1358a5c72737SRavi Kumar } 1359a5c72737SRavi Kumar } 1360a5c72737SRavi Kumar 1361a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_baset_mode(struct axgbe_phy_data *phy_data 1362a5c72737SRavi Kumar __rte_unused, 1363a5c72737SRavi Kumar int speed) 1364a5c72737SRavi Kumar { 1365a5c72737SRavi Kumar switch (speed) { 1366a5c72737SRavi Kumar case SPEED_100: 1367a5c72737SRavi Kumar return AXGBE_MODE_SGMII_100; 1368a5c72737SRavi Kumar case SPEED_1000: 1369a5c72737SRavi Kumar return AXGBE_MODE_SGMII_1000; 1370a5c72737SRavi Kumar case SPEED_10000: 1371a5c72737SRavi Kumar return AXGBE_MODE_KR; 1372a5c72737SRavi Kumar default: 1373a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1374a5c72737SRavi Kumar } 1375a5c72737SRavi Kumar } 1376a5c72737SRavi Kumar 1377a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_sfp_mode(struct axgbe_phy_data *phy_data, 1378a5c72737SRavi Kumar int speed) 1379a5c72737SRavi Kumar { 1380a5c72737SRavi Kumar switch (speed) { 1381a5c72737SRavi Kumar case SPEED_100: 1382a5c72737SRavi Kumar return AXGBE_MODE_SGMII_100; 1383a5c72737SRavi Kumar case SPEED_1000: 1384a5c72737SRavi Kumar if (phy_data->sfp_base == AXGBE_SFP_BASE_1000_T) 1385a5c72737SRavi Kumar return AXGBE_MODE_SGMII_1000; 1386a5c72737SRavi Kumar else 1387a5c72737SRavi Kumar return AXGBE_MODE_X; 1388a5c72737SRavi Kumar case SPEED_10000: 1389a5c72737SRavi Kumar case SPEED_UNKNOWN: 1390a5c72737SRavi Kumar return AXGBE_MODE_SFI; 1391a5c72737SRavi Kumar default: 1392a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1393a5c72737SRavi Kumar } 1394a5c72737SRavi Kumar } 1395a5c72737SRavi Kumar 1396a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_bp_2500_mode(int speed) 1397a5c72737SRavi Kumar { 1398a5c72737SRavi Kumar switch (speed) { 1399a5c72737SRavi Kumar case SPEED_2500: 1400a5c72737SRavi Kumar return AXGBE_MODE_KX_2500; 1401a5c72737SRavi Kumar default: 1402a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1403a5c72737SRavi Kumar } 1404a5c72737SRavi Kumar } 1405a5c72737SRavi Kumar 1406a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_bp_mode(int speed) 1407a5c72737SRavi Kumar { 1408a5c72737SRavi Kumar switch (speed) { 1409a5c72737SRavi Kumar case SPEED_1000: 1410a5c72737SRavi Kumar return AXGBE_MODE_KX_1000; 1411a5c72737SRavi Kumar case SPEED_10000: 1412a5c72737SRavi Kumar return AXGBE_MODE_KR; 1413a5c72737SRavi Kumar default: 1414a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1415a5c72737SRavi Kumar } 1416a5c72737SRavi Kumar } 1417a5c72737SRavi Kumar 1418a5c72737SRavi Kumar static enum axgbe_mode axgbe_phy_get_mode(struct axgbe_port *pdata, 1419a5c72737SRavi Kumar int speed) 1420a5c72737SRavi Kumar { 1421a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1422a5c72737SRavi Kumar 1423a5c72737SRavi Kumar switch (phy_data->port_mode) { 1424a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 1425a5c72737SRavi Kumar return axgbe_phy_get_bp_mode(speed); 1426a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 1427a5c72737SRavi Kumar return axgbe_phy_get_bp_2500_mode(speed); 1428a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 1429a5c72737SRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 1430a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 1431a5c72737SRavi Kumar return axgbe_phy_get_baset_mode(phy_data, speed); 1432a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 1433a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 1434a5c72737SRavi Kumar return axgbe_phy_get_basex_mode(phy_data, speed); 1435a5c72737SRavi Kumar case AXGBE_PORT_MODE_SFP: 1436a5c72737SRavi Kumar return axgbe_phy_get_sfp_mode(phy_data, speed); 1437a5c72737SRavi Kumar default: 1438a5c72737SRavi Kumar return AXGBE_MODE_UNKNOWN; 1439a5c72737SRavi Kumar } 1440a5c72737SRavi Kumar } 1441a5c72737SRavi Kumar 1442a5c72737SRavi Kumar static void axgbe_phy_set_mode(struct axgbe_port *pdata, enum axgbe_mode mode) 1443a5c72737SRavi Kumar { 1444a5c72737SRavi Kumar switch (mode) { 1445a5c72737SRavi Kumar case AXGBE_MODE_KR: 1446a5c72737SRavi Kumar axgbe_phy_kr_mode(pdata); 1447a5c72737SRavi Kumar break; 1448a5c72737SRavi Kumar case AXGBE_MODE_SFI: 1449a5c72737SRavi Kumar axgbe_phy_sfi_mode(pdata); 1450a5c72737SRavi Kumar break; 1451*936e294cSGirish Nandibasappa case AXGBE_MODE_KX_2500: 1452*936e294cSGirish Nandibasappa axgbe_phy_kx_2500_mode(pdata); 1453*936e294cSGirish Nandibasappa break; 1454*936e294cSGirish Nandibasappa case AXGBE_MODE_SGMII_1000: 1455*936e294cSGirish Nandibasappa axgbe_phy_sgmii_1000_mode(pdata); 1456*936e294cSGirish Nandibasappa break; 1457a5c72737SRavi Kumar default: 1458a5c72737SRavi Kumar break; 1459a5c72737SRavi Kumar } 1460a5c72737SRavi Kumar } 1461a5c72737SRavi Kumar 1462a5c72737SRavi Kumar static bool axgbe_phy_check_mode(struct axgbe_port *pdata, 1463a5c72737SRavi Kumar enum axgbe_mode mode, u32 advert) 1464a5c72737SRavi Kumar { 1465a5c72737SRavi Kumar if (pdata->phy.autoneg == AUTONEG_ENABLE) { 1466a5c72737SRavi Kumar if (pdata->phy.advertising & advert) 1467a5c72737SRavi Kumar return true; 1468a5c72737SRavi Kumar } else { 1469a5c72737SRavi Kumar enum axgbe_mode cur_mode; 1470a5c72737SRavi Kumar 1471a5c72737SRavi Kumar cur_mode = axgbe_phy_get_mode(pdata, pdata->phy.speed); 1472a5c72737SRavi Kumar if (cur_mode == mode) 1473a5c72737SRavi Kumar return true; 1474a5c72737SRavi Kumar } 1475a5c72737SRavi Kumar 1476a5c72737SRavi Kumar return false; 1477a5c72737SRavi Kumar } 1478a5c72737SRavi Kumar 1479a5c72737SRavi Kumar static bool axgbe_phy_use_basex_mode(struct axgbe_port *pdata, 1480a5c72737SRavi Kumar enum axgbe_mode mode) 1481a5c72737SRavi Kumar { 1482a5c72737SRavi Kumar switch (mode) { 1483a5c72737SRavi Kumar case AXGBE_MODE_X: 1484a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1485a5c72737SRavi Kumar ADVERTISED_1000baseT_Full); 1486a5c72737SRavi Kumar case AXGBE_MODE_KR: 1487a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1488a5c72737SRavi Kumar ADVERTISED_10000baseT_Full); 1489a5c72737SRavi Kumar default: 1490a5c72737SRavi Kumar return false; 1491a5c72737SRavi Kumar } 1492a5c72737SRavi Kumar } 1493a5c72737SRavi Kumar 1494a5c72737SRavi Kumar static bool axgbe_phy_use_baset_mode(struct axgbe_port *pdata, 1495a5c72737SRavi Kumar enum axgbe_mode mode) 1496a5c72737SRavi Kumar { 1497a5c72737SRavi Kumar switch (mode) { 1498a5c72737SRavi Kumar case AXGBE_MODE_SGMII_100: 1499a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1500a5c72737SRavi Kumar ADVERTISED_100baseT_Full); 1501a5c72737SRavi Kumar case AXGBE_MODE_SGMII_1000: 1502a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1503a5c72737SRavi Kumar ADVERTISED_1000baseT_Full); 1504a5c72737SRavi Kumar case AXGBE_MODE_KR: 1505a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1506a5c72737SRavi Kumar ADVERTISED_10000baseT_Full); 1507a5c72737SRavi Kumar default: 1508a5c72737SRavi Kumar return false; 1509a5c72737SRavi Kumar } 1510a5c72737SRavi Kumar } 1511a5c72737SRavi Kumar 1512a5c72737SRavi Kumar static bool axgbe_phy_use_sfp_mode(struct axgbe_port *pdata, 1513a5c72737SRavi Kumar enum axgbe_mode mode) 1514a5c72737SRavi Kumar { 1515a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1516a5c72737SRavi Kumar 1517a5c72737SRavi Kumar switch (mode) { 1518a5c72737SRavi Kumar case AXGBE_MODE_X: 1519a5c72737SRavi Kumar if (phy_data->sfp_base == AXGBE_SFP_BASE_1000_T) 1520a5c72737SRavi Kumar return false; 1521a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1522a5c72737SRavi Kumar ADVERTISED_1000baseT_Full); 1523a5c72737SRavi Kumar case AXGBE_MODE_SGMII_100: 1524a5c72737SRavi Kumar if (phy_data->sfp_base != AXGBE_SFP_BASE_1000_T) 1525a5c72737SRavi Kumar return false; 1526a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1527a5c72737SRavi Kumar ADVERTISED_100baseT_Full); 1528a5c72737SRavi Kumar case AXGBE_MODE_SGMII_1000: 1529a5c72737SRavi Kumar if (phy_data->sfp_base != AXGBE_SFP_BASE_1000_T) 1530a5c72737SRavi Kumar return false; 1531a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1532a5c72737SRavi Kumar ADVERTISED_1000baseT_Full); 1533a5c72737SRavi Kumar case AXGBE_MODE_SFI: 1534a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1535a5c72737SRavi Kumar ADVERTISED_10000baseT_Full); 1536a5c72737SRavi Kumar default: 1537a5c72737SRavi Kumar return false; 1538a5c72737SRavi Kumar } 1539a5c72737SRavi Kumar } 1540a5c72737SRavi Kumar 1541a5c72737SRavi Kumar static bool axgbe_phy_use_bp_2500_mode(struct axgbe_port *pdata, 1542a5c72737SRavi Kumar enum axgbe_mode mode) 1543a5c72737SRavi Kumar { 1544a5c72737SRavi Kumar switch (mode) { 1545a5c72737SRavi Kumar case AXGBE_MODE_KX_2500: 1546a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1547a5c72737SRavi Kumar ADVERTISED_2500baseX_Full); 1548a5c72737SRavi Kumar default: 1549a5c72737SRavi Kumar return false; 1550a5c72737SRavi Kumar } 1551a5c72737SRavi Kumar } 1552a5c72737SRavi Kumar 1553a5c72737SRavi Kumar static bool axgbe_phy_use_bp_mode(struct axgbe_port *pdata, 1554a5c72737SRavi Kumar enum axgbe_mode mode) 1555a5c72737SRavi Kumar { 1556a5c72737SRavi Kumar switch (mode) { 1557a5c72737SRavi Kumar case AXGBE_MODE_KX_1000: 1558a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1559a5c72737SRavi Kumar ADVERTISED_1000baseKX_Full); 1560a5c72737SRavi Kumar case AXGBE_MODE_KR: 1561a5c72737SRavi Kumar return axgbe_phy_check_mode(pdata, mode, 1562a5c72737SRavi Kumar ADVERTISED_10000baseKR_Full); 1563a5c72737SRavi Kumar default: 1564a5c72737SRavi Kumar return false; 1565a5c72737SRavi Kumar } 1566a5c72737SRavi Kumar } 1567a5c72737SRavi Kumar 1568a5c72737SRavi Kumar static bool axgbe_phy_use_mode(struct axgbe_port *pdata, enum axgbe_mode mode) 1569a5c72737SRavi Kumar { 1570a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1571a5c72737SRavi Kumar 1572a5c72737SRavi Kumar switch (phy_data->port_mode) { 1573a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 1574a5c72737SRavi Kumar return axgbe_phy_use_bp_mode(pdata, mode); 1575a5c72737SRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 1576a5c72737SRavi Kumar return axgbe_phy_use_bp_2500_mode(pdata, mode); 1577a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 1578a5c72737SRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 1579a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 1580a5c72737SRavi Kumar return axgbe_phy_use_baset_mode(pdata, mode); 1581a5c72737SRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 1582a5c72737SRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 1583a5c72737SRavi Kumar return axgbe_phy_use_basex_mode(pdata, mode); 1584a5c72737SRavi Kumar case AXGBE_PORT_MODE_SFP: 1585a5c72737SRavi Kumar return axgbe_phy_use_sfp_mode(pdata, mode); 1586a5c72737SRavi Kumar default: 1587a5c72737SRavi Kumar return false; 1588a5c72737SRavi Kumar } 1589a5c72737SRavi Kumar } 1590a5c72737SRavi Kumar 1591a5c72737SRavi Kumar static int axgbe_phy_link_status(struct axgbe_port *pdata, int *an_restart) 1592a5c72737SRavi Kumar { 1593a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1594a5c72737SRavi Kumar unsigned int reg; 1595a5c72737SRavi Kumar 1596a5c72737SRavi Kumar *an_restart = 0; 1597a5c72737SRavi Kumar 1598a5c72737SRavi Kumar if (phy_data->port_mode == AXGBE_PORT_MODE_SFP) { 1599a5c72737SRavi Kumar /* Check SFP signals */ 1600a5c72737SRavi Kumar axgbe_phy_sfp_detect(pdata); 1601a5c72737SRavi Kumar 1602a5c72737SRavi Kumar if (phy_data->sfp_changed) { 1603a5c72737SRavi Kumar *an_restart = 1; 1604a5c72737SRavi Kumar return 0; 1605a5c72737SRavi Kumar } 1606a5c72737SRavi Kumar 1607a5c72737SRavi Kumar if (phy_data->sfp_mod_absent || phy_data->sfp_rx_los) 1608a5c72737SRavi Kumar return 0; 1609a5c72737SRavi Kumar } 1610a5c72737SRavi Kumar 1611a5c72737SRavi Kumar /* Link status is latched low, so read once to clear 1612a5c72737SRavi Kumar * and then read again to get current state 1613a5c72737SRavi Kumar */ 1614a5c72737SRavi Kumar reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1); 1615a5c72737SRavi Kumar reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1); 1616a5c72737SRavi Kumar if (reg & MDIO_STAT1_LSTATUS) 1617a5c72737SRavi Kumar return 1; 1618a5c72737SRavi Kumar 1619a5c72737SRavi Kumar /* No link, attempt a receiver reset cycle */ 1620a5c72737SRavi Kumar if (phy_data->rrc_count++) { 1621a5c72737SRavi Kumar phy_data->rrc_count = 0; 1622a5c72737SRavi Kumar axgbe_phy_rrc(pdata); 1623a5c72737SRavi Kumar } 1624a5c72737SRavi Kumar 1625a5c72737SRavi Kumar return 0; 1626a5c72737SRavi Kumar } 1627a5c72737SRavi Kumar 16284ac7516bSRavi Kumar static void axgbe_phy_sfp_gpio_setup(struct axgbe_port *pdata) 16294ac7516bSRavi Kumar { 16304ac7516bSRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 16314ac7516bSRavi Kumar unsigned int reg; 16324ac7516bSRavi Kumar 16334ac7516bSRavi Kumar reg = XP_IOREAD(pdata, XP_PROP_3); 16344ac7516bSRavi Kumar 16354ac7516bSRavi Kumar phy_data->sfp_gpio_address = AXGBE_GPIO_ADDRESS_PCA9555 + 16364ac7516bSRavi Kumar XP_GET_BITS(reg, XP_PROP_3, GPIO_ADDR); 16374ac7516bSRavi Kumar 16384ac7516bSRavi Kumar phy_data->sfp_gpio_mask = XP_GET_BITS(reg, XP_PROP_3, GPIO_MASK); 16394ac7516bSRavi Kumar 16404ac7516bSRavi Kumar phy_data->sfp_gpio_rx_los = XP_GET_BITS(reg, XP_PROP_3, 16414ac7516bSRavi Kumar GPIO_RX_LOS); 16424ac7516bSRavi Kumar phy_data->sfp_gpio_tx_fault = XP_GET_BITS(reg, XP_PROP_3, 16434ac7516bSRavi Kumar GPIO_TX_FAULT); 16444ac7516bSRavi Kumar phy_data->sfp_gpio_mod_absent = XP_GET_BITS(reg, XP_PROP_3, 16454ac7516bSRavi Kumar GPIO_MOD_ABS); 16464ac7516bSRavi Kumar phy_data->sfp_gpio_rate_select = XP_GET_BITS(reg, XP_PROP_3, 16474ac7516bSRavi Kumar GPIO_RATE_SELECT); 16484ac7516bSRavi Kumar } 16494ac7516bSRavi Kumar 16504ac7516bSRavi Kumar static void axgbe_phy_sfp_comm_setup(struct axgbe_port *pdata) 16514ac7516bSRavi Kumar { 16524ac7516bSRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 16534ac7516bSRavi Kumar unsigned int reg, mux_addr_hi, mux_addr_lo; 16544ac7516bSRavi Kumar 16554ac7516bSRavi Kumar reg = XP_IOREAD(pdata, XP_PROP_4); 16564ac7516bSRavi Kumar 16574ac7516bSRavi Kumar mux_addr_hi = XP_GET_BITS(reg, XP_PROP_4, MUX_ADDR_HI); 16584ac7516bSRavi Kumar mux_addr_lo = XP_GET_BITS(reg, XP_PROP_4, MUX_ADDR_LO); 16594ac7516bSRavi Kumar if (mux_addr_lo == AXGBE_SFP_DIRECT) 16604ac7516bSRavi Kumar return; 16614ac7516bSRavi Kumar 16624ac7516bSRavi Kumar phy_data->sfp_comm = AXGBE_SFP_COMM_PCA9545; 16634ac7516bSRavi Kumar phy_data->sfp_mux_address = (mux_addr_hi << 2) + mux_addr_lo; 16644ac7516bSRavi Kumar phy_data->sfp_mux_channel = XP_GET_BITS(reg, XP_PROP_4, MUX_CHAN); 16654ac7516bSRavi Kumar } 16664ac7516bSRavi Kumar 16674ac7516bSRavi Kumar static void axgbe_phy_sfp_setup(struct axgbe_port *pdata) 16684ac7516bSRavi Kumar { 16694ac7516bSRavi Kumar axgbe_phy_sfp_comm_setup(pdata); 16704ac7516bSRavi Kumar axgbe_phy_sfp_gpio_setup(pdata); 16714ac7516bSRavi Kumar } 16724ac7516bSRavi Kumar 16734ac7516bSRavi Kumar static bool axgbe_phy_redrv_error(struct axgbe_phy_data *phy_data) 16744ac7516bSRavi Kumar { 16754ac7516bSRavi Kumar if (!phy_data->redrv) 16764ac7516bSRavi Kumar return false; 16774ac7516bSRavi Kumar 16784ac7516bSRavi Kumar if (phy_data->redrv_if >= AXGBE_PHY_REDRV_IF_MAX) 16794ac7516bSRavi Kumar return true; 16804ac7516bSRavi Kumar 16814ac7516bSRavi Kumar switch (phy_data->redrv_model) { 16824ac7516bSRavi Kumar case AXGBE_PHY_REDRV_MODEL_4223: 16834ac7516bSRavi Kumar if (phy_data->redrv_lane > 3) 16844ac7516bSRavi Kumar return true; 16854ac7516bSRavi Kumar break; 16864ac7516bSRavi Kumar case AXGBE_PHY_REDRV_MODEL_4227: 16874ac7516bSRavi Kumar if (phy_data->redrv_lane > 1) 16884ac7516bSRavi Kumar return true; 16894ac7516bSRavi Kumar break; 16904ac7516bSRavi Kumar default: 16914ac7516bSRavi Kumar return true; 16924ac7516bSRavi Kumar } 16934ac7516bSRavi Kumar 16944ac7516bSRavi Kumar return false; 16954ac7516bSRavi Kumar } 16964ac7516bSRavi Kumar 16974ac7516bSRavi Kumar static int axgbe_phy_mdio_reset_setup(struct axgbe_port *pdata) 16984ac7516bSRavi Kumar { 16994ac7516bSRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 17004ac7516bSRavi Kumar unsigned int reg; 17014ac7516bSRavi Kumar 17024ac7516bSRavi Kumar if (phy_data->conn_type != AXGBE_CONN_TYPE_MDIO) 17034ac7516bSRavi Kumar return 0; 17044ac7516bSRavi Kumar reg = XP_IOREAD(pdata, XP_PROP_3); 17054ac7516bSRavi Kumar phy_data->mdio_reset = XP_GET_BITS(reg, XP_PROP_3, MDIO_RESET); 17064ac7516bSRavi Kumar switch (phy_data->mdio_reset) { 17074ac7516bSRavi Kumar case AXGBE_MDIO_RESET_NONE: 17084ac7516bSRavi Kumar case AXGBE_MDIO_RESET_I2C_GPIO: 17094ac7516bSRavi Kumar case AXGBE_MDIO_RESET_INT_GPIO: 17104ac7516bSRavi Kumar break; 17114ac7516bSRavi Kumar default: 17124ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "unsupported MDIO reset (%#x)\n", 17134ac7516bSRavi Kumar phy_data->mdio_reset); 17144ac7516bSRavi Kumar return -EINVAL; 17154ac7516bSRavi Kumar } 17164ac7516bSRavi Kumar if (phy_data->mdio_reset == AXGBE_MDIO_RESET_I2C_GPIO) { 17174ac7516bSRavi Kumar phy_data->mdio_reset_addr = AXGBE_GPIO_ADDRESS_PCA9555 + 17184ac7516bSRavi Kumar XP_GET_BITS(reg, XP_PROP_3, 17194ac7516bSRavi Kumar MDIO_RESET_I2C_ADDR); 17204ac7516bSRavi Kumar phy_data->mdio_reset_gpio = XP_GET_BITS(reg, XP_PROP_3, 17214ac7516bSRavi Kumar MDIO_RESET_I2C_GPIO); 17224ac7516bSRavi Kumar } else if (phy_data->mdio_reset == AXGBE_MDIO_RESET_INT_GPIO) { 17234ac7516bSRavi Kumar phy_data->mdio_reset_gpio = XP_GET_BITS(reg, XP_PROP_3, 17244ac7516bSRavi Kumar MDIO_RESET_INT_GPIO); 17254ac7516bSRavi Kumar } 17264ac7516bSRavi Kumar 17274ac7516bSRavi Kumar return 0; 17284ac7516bSRavi Kumar } 17294ac7516bSRavi Kumar 17304ac7516bSRavi Kumar static bool axgbe_phy_port_mode_mismatch(struct axgbe_port *pdata) 17314ac7516bSRavi Kumar { 17324ac7516bSRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 17334ac7516bSRavi Kumar 17344ac7516bSRavi Kumar switch (phy_data->port_mode) { 17354ac7516bSRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 17364ac7516bSRavi Kumar if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) || 17374ac7516bSRavi Kumar (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000)) 17384ac7516bSRavi Kumar return false; 17394ac7516bSRavi Kumar break; 17404ac7516bSRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 17414ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500) 17424ac7516bSRavi Kumar return false; 17434ac7516bSRavi Kumar break; 17444ac7516bSRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 17454ac7516bSRavi Kumar if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) || 17464ac7516bSRavi Kumar (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000)) 17474ac7516bSRavi Kumar return false; 17484ac7516bSRavi Kumar break; 17494ac7516bSRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 17504ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) 17514ac7516bSRavi Kumar return false; 17524ac7516bSRavi Kumar break; 17534ac7516bSRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 17544ac7516bSRavi Kumar if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) || 17554ac7516bSRavi Kumar (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) || 17564ac7516bSRavi Kumar (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500)) 17574ac7516bSRavi Kumar return false; 17584ac7516bSRavi Kumar break; 17594ac7516bSRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 17604ac7516bSRavi Kumar if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) || 17614ac7516bSRavi Kumar (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) || 17624ac7516bSRavi Kumar (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000)) 17634ac7516bSRavi Kumar return false; 17644ac7516bSRavi Kumar break; 17654ac7516bSRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 17664ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) 17674ac7516bSRavi Kumar return false; 17684ac7516bSRavi Kumar break; 17694ac7516bSRavi Kumar case AXGBE_PORT_MODE_SFP: 17704ac7516bSRavi Kumar if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) || 17714ac7516bSRavi Kumar (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) || 17724ac7516bSRavi Kumar (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000)) 17734ac7516bSRavi Kumar return false; 17744ac7516bSRavi Kumar break; 17754ac7516bSRavi Kumar default: 17764ac7516bSRavi Kumar break; 17774ac7516bSRavi Kumar } 17784ac7516bSRavi Kumar 17794ac7516bSRavi Kumar return true; 17804ac7516bSRavi Kumar } 17814ac7516bSRavi Kumar 17824ac7516bSRavi Kumar static bool axgbe_phy_conn_type_mismatch(struct axgbe_port *pdata) 17834ac7516bSRavi Kumar { 17844ac7516bSRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 17854ac7516bSRavi Kumar 17864ac7516bSRavi Kumar switch (phy_data->port_mode) { 17874ac7516bSRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 17884ac7516bSRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 17894ac7516bSRavi Kumar if (phy_data->conn_type == AXGBE_CONN_TYPE_BACKPLANE) 17904ac7516bSRavi Kumar return false; 17914ac7516bSRavi Kumar break; 17924ac7516bSRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 17934ac7516bSRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 17944ac7516bSRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 17954ac7516bSRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 17964ac7516bSRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 17974ac7516bSRavi Kumar if (phy_data->conn_type == AXGBE_CONN_TYPE_MDIO) 17984ac7516bSRavi Kumar return false; 17994ac7516bSRavi Kumar break; 18004ac7516bSRavi Kumar case AXGBE_PORT_MODE_SFP: 18014ac7516bSRavi Kumar if (phy_data->conn_type == AXGBE_CONN_TYPE_SFP) 18024ac7516bSRavi Kumar return false; 18034ac7516bSRavi Kumar break; 18044ac7516bSRavi Kumar default: 18054ac7516bSRavi Kumar break; 18064ac7516bSRavi Kumar } 18074ac7516bSRavi Kumar 18084ac7516bSRavi Kumar return true; 18094ac7516bSRavi Kumar } 18104ac7516bSRavi Kumar 18114ac7516bSRavi Kumar static bool axgbe_phy_port_enabled(struct axgbe_port *pdata) 18124ac7516bSRavi Kumar { 18134ac7516bSRavi Kumar unsigned int reg; 18144ac7516bSRavi Kumar 18154ac7516bSRavi Kumar reg = XP_IOREAD(pdata, XP_PROP_0); 18164ac7516bSRavi Kumar if (!XP_GET_BITS(reg, XP_PROP_0, PORT_SPEEDS)) 18174ac7516bSRavi Kumar return false; 18184ac7516bSRavi Kumar if (!XP_GET_BITS(reg, XP_PROP_0, CONN_TYPE)) 18194ac7516bSRavi Kumar return false; 18204ac7516bSRavi Kumar 18214ac7516bSRavi Kumar return true; 18224ac7516bSRavi Kumar } 18234ac7516bSRavi Kumar 182400072056SRavi Kumar static void axgbe_phy_cdr_track(struct axgbe_port *pdata) 182500072056SRavi Kumar { 182600072056SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 182700072056SRavi Kumar 182800072056SRavi Kumar if (!pdata->vdata->an_cdr_workaround) 182900072056SRavi Kumar return; 183000072056SRavi Kumar 183100072056SRavi Kumar if (!phy_data->phy_cdr_notrack) 183200072056SRavi Kumar return; 183300072056SRavi Kumar 183400072056SRavi Kumar rte_delay_us(phy_data->phy_cdr_delay + 400); 183500072056SRavi Kumar 183600072056SRavi Kumar XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_CDR_CONTROL, 183700072056SRavi Kumar AXGBE_PMA_CDR_TRACK_EN_MASK, 183800072056SRavi Kumar AXGBE_PMA_CDR_TRACK_EN_ON); 183900072056SRavi Kumar 184000072056SRavi Kumar phy_data->phy_cdr_notrack = 0; 184100072056SRavi Kumar } 184200072056SRavi Kumar 184300072056SRavi Kumar static void axgbe_phy_cdr_notrack(struct axgbe_port *pdata) 184400072056SRavi Kumar { 184500072056SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 184600072056SRavi Kumar 184700072056SRavi Kumar if (!pdata->vdata->an_cdr_workaround) 184800072056SRavi Kumar return; 184900072056SRavi Kumar 185000072056SRavi Kumar if (phy_data->phy_cdr_notrack) 185100072056SRavi Kumar return; 185200072056SRavi Kumar 185300072056SRavi Kumar XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_CDR_CONTROL, 185400072056SRavi Kumar AXGBE_PMA_CDR_TRACK_EN_MASK, 185500072056SRavi Kumar AXGBE_PMA_CDR_TRACK_EN_OFF); 185600072056SRavi Kumar 185700072056SRavi Kumar axgbe_phy_rrc(pdata); 185800072056SRavi Kumar 185900072056SRavi Kumar phy_data->phy_cdr_notrack = 1; 186000072056SRavi Kumar } 186100072056SRavi Kumar 186200072056SRavi Kumar static void axgbe_phy_kr_training_post(struct axgbe_port *pdata) 186300072056SRavi Kumar { 186400072056SRavi Kumar if (!pdata->cdr_track_early) 186500072056SRavi Kumar axgbe_phy_cdr_track(pdata); 186600072056SRavi Kumar } 186700072056SRavi Kumar 186800072056SRavi Kumar static void axgbe_phy_kr_training_pre(struct axgbe_port *pdata) 186900072056SRavi Kumar { 187000072056SRavi Kumar if (pdata->cdr_track_early) 187100072056SRavi Kumar axgbe_phy_cdr_track(pdata); 187200072056SRavi Kumar } 187300072056SRavi Kumar 187400072056SRavi Kumar static void axgbe_phy_an_post(struct axgbe_port *pdata) 187500072056SRavi Kumar { 187600072056SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 187700072056SRavi Kumar 187800072056SRavi Kumar switch (pdata->an_mode) { 187900072056SRavi Kumar case AXGBE_AN_MODE_CL73: 188000072056SRavi Kumar case AXGBE_AN_MODE_CL73_REDRV: 188100072056SRavi Kumar if (phy_data->cur_mode != AXGBE_MODE_KR) 188200072056SRavi Kumar break; 188300072056SRavi Kumar 188400072056SRavi Kumar axgbe_phy_cdr_track(pdata); 188500072056SRavi Kumar 188600072056SRavi Kumar switch (pdata->an_result) { 188700072056SRavi Kumar case AXGBE_AN_READY: 188800072056SRavi Kumar case AXGBE_AN_COMPLETE: 188900072056SRavi Kumar break; 189000072056SRavi Kumar default: 189100072056SRavi Kumar if (phy_data->phy_cdr_delay < AXGBE_CDR_DELAY_MAX) 189200072056SRavi Kumar phy_data->phy_cdr_delay += AXGBE_CDR_DELAY_INC; 189300072056SRavi Kumar break; 189400072056SRavi Kumar } 189500072056SRavi Kumar break; 189600072056SRavi Kumar default: 189700072056SRavi Kumar break; 189800072056SRavi Kumar } 189900072056SRavi Kumar } 190000072056SRavi Kumar 190100072056SRavi Kumar static void axgbe_phy_an_pre(struct axgbe_port *pdata) 190200072056SRavi Kumar { 190300072056SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 190400072056SRavi Kumar 190500072056SRavi Kumar switch (pdata->an_mode) { 190600072056SRavi Kumar case AXGBE_AN_MODE_CL73: 190700072056SRavi Kumar case AXGBE_AN_MODE_CL73_REDRV: 190800072056SRavi Kumar if (phy_data->cur_mode != AXGBE_MODE_KR) 190900072056SRavi Kumar break; 191000072056SRavi Kumar 191100072056SRavi Kumar axgbe_phy_cdr_notrack(pdata); 191200072056SRavi Kumar break; 191300072056SRavi Kumar default: 191400072056SRavi Kumar break; 191500072056SRavi Kumar } 191600072056SRavi Kumar } 191700072056SRavi Kumar 1918a5c72737SRavi Kumar static void axgbe_phy_stop(struct axgbe_port *pdata) 1919a5c72737SRavi Kumar { 1920a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1921a5c72737SRavi Kumar 1922a5c72737SRavi Kumar /* Reset SFP data */ 1923a5c72737SRavi Kumar axgbe_phy_sfp_reset(phy_data); 1924a5c72737SRavi Kumar axgbe_phy_sfp_mod_absent(pdata); 1925a5c72737SRavi Kumar 192600072056SRavi Kumar /* Reset CDR support */ 192700072056SRavi Kumar axgbe_phy_cdr_track(pdata); 192800072056SRavi Kumar 1929a5c72737SRavi Kumar /* Power off the PHY */ 1930a5c72737SRavi Kumar axgbe_phy_power_off(pdata); 1931a5c72737SRavi Kumar 1932a5c72737SRavi Kumar /* Stop the I2C controller */ 1933a5c72737SRavi Kumar pdata->i2c_if.i2c_stop(pdata); 1934a5c72737SRavi Kumar } 1935a5c72737SRavi Kumar 1936a5c72737SRavi Kumar static int axgbe_phy_start(struct axgbe_port *pdata) 1937a5c72737SRavi Kumar { 1938a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1939a5c72737SRavi Kumar int ret; 1940a5c72737SRavi Kumar 1941a5c72737SRavi Kumar /* Start the I2C controller */ 1942a5c72737SRavi Kumar ret = pdata->i2c_if.i2c_start(pdata); 1943a5c72737SRavi Kumar if (ret) 1944a5c72737SRavi Kumar return ret; 1945a5c72737SRavi Kumar 1946a5c72737SRavi Kumar /* Start in highest supported mode */ 1947a5c72737SRavi Kumar axgbe_phy_set_mode(pdata, phy_data->start_mode); 1948a5c72737SRavi Kumar 194900072056SRavi Kumar /* Reset CDR support */ 195000072056SRavi Kumar axgbe_phy_cdr_track(pdata); 195100072056SRavi Kumar 1952a5c72737SRavi Kumar /* After starting the I2C controller, we can check for an SFP */ 1953a5c72737SRavi Kumar switch (phy_data->port_mode) { 1954a5c72737SRavi Kumar case AXGBE_PORT_MODE_SFP: 1955a5c72737SRavi Kumar axgbe_phy_sfp_detect(pdata); 1956a5c72737SRavi Kumar break; 1957a5c72737SRavi Kumar default: 1958a5c72737SRavi Kumar break; 1959a5c72737SRavi Kumar } 1960a5c72737SRavi Kumar 1961a5c72737SRavi Kumar return ret; 1962a5c72737SRavi Kumar } 1963a5c72737SRavi Kumar 1964a5c72737SRavi Kumar static int axgbe_phy_reset(struct axgbe_port *pdata) 1965a5c72737SRavi Kumar { 1966a5c72737SRavi Kumar struct axgbe_phy_data *phy_data = pdata->phy_data; 1967a5c72737SRavi Kumar enum axgbe_mode cur_mode; 1968a5c72737SRavi Kumar 1969a5c72737SRavi Kumar /* Reset by power cycling the PHY */ 1970a5c72737SRavi Kumar cur_mode = phy_data->cur_mode; 1971a5c72737SRavi Kumar axgbe_phy_power_off(pdata); 1972a5c72737SRavi Kumar /* First time reset is done with passed unknown mode*/ 1973a5c72737SRavi Kumar axgbe_phy_set_mode(pdata, cur_mode); 1974a5c72737SRavi Kumar return 0; 1975a5c72737SRavi Kumar } 1976a5c72737SRavi Kumar 19774ac7516bSRavi Kumar static int axgbe_phy_init(struct axgbe_port *pdata) 19784ac7516bSRavi Kumar { 19794ac7516bSRavi Kumar struct axgbe_phy_data *phy_data; 19804ac7516bSRavi Kumar unsigned int reg; 19814ac7516bSRavi Kumar int ret; 19824ac7516bSRavi Kumar 19834ac7516bSRavi Kumar /* Check if enabled */ 19844ac7516bSRavi Kumar if (!axgbe_phy_port_enabled(pdata)) { 19854ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "device is not enabled\n"); 19864ac7516bSRavi Kumar return -ENODEV; 19874ac7516bSRavi Kumar } 19884ac7516bSRavi Kumar 19894ac7516bSRavi Kumar /* Initialize the I2C controller */ 19904ac7516bSRavi Kumar ret = pdata->i2c_if.i2c_init(pdata); 19914ac7516bSRavi Kumar if (ret) 19924ac7516bSRavi Kumar return ret; 19934ac7516bSRavi Kumar 19944ac7516bSRavi Kumar phy_data = rte_zmalloc("phy_data memory", sizeof(*phy_data), 0); 19954ac7516bSRavi Kumar if (!phy_data) { 19964ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "phy_data allocation failed\n"); 19974ac7516bSRavi Kumar return -ENOMEM; 19984ac7516bSRavi Kumar } 19994ac7516bSRavi Kumar pdata->phy_data = phy_data; 20004ac7516bSRavi Kumar 20014ac7516bSRavi Kumar reg = XP_IOREAD(pdata, XP_PROP_0); 20024ac7516bSRavi Kumar phy_data->port_mode = XP_GET_BITS(reg, XP_PROP_0, PORT_MODE); 20034ac7516bSRavi Kumar phy_data->port_id = XP_GET_BITS(reg, XP_PROP_0, PORT_ID); 20044ac7516bSRavi Kumar phy_data->port_speeds = XP_GET_BITS(reg, XP_PROP_0, PORT_SPEEDS); 20054ac7516bSRavi Kumar phy_data->conn_type = XP_GET_BITS(reg, XP_PROP_0, CONN_TYPE); 20064ac7516bSRavi Kumar phy_data->mdio_addr = XP_GET_BITS(reg, XP_PROP_0, MDIO_ADDR); 20074ac7516bSRavi Kumar 20084ac7516bSRavi Kumar reg = XP_IOREAD(pdata, XP_PROP_4); 20094ac7516bSRavi Kumar phy_data->redrv = XP_GET_BITS(reg, XP_PROP_4, REDRV_PRESENT); 20104ac7516bSRavi Kumar phy_data->redrv_if = XP_GET_BITS(reg, XP_PROP_4, REDRV_IF); 20114ac7516bSRavi Kumar phy_data->redrv_addr = XP_GET_BITS(reg, XP_PROP_4, REDRV_ADDR); 20124ac7516bSRavi Kumar phy_data->redrv_lane = XP_GET_BITS(reg, XP_PROP_4, REDRV_LANE); 20134ac7516bSRavi Kumar phy_data->redrv_model = XP_GET_BITS(reg, XP_PROP_4, REDRV_MODEL); 20144ac7516bSRavi Kumar 20154ac7516bSRavi Kumar /* Validate the connection requested */ 20164ac7516bSRavi Kumar if (axgbe_phy_conn_type_mismatch(pdata)) { 20174ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "phy mode/connection mismatch (%#x/%#x)\n", 20184ac7516bSRavi Kumar phy_data->port_mode, phy_data->conn_type); 20194ac7516bSRavi Kumar return -EINVAL; 20204ac7516bSRavi Kumar } 20214ac7516bSRavi Kumar 20224ac7516bSRavi Kumar /* Validate the mode requested */ 20234ac7516bSRavi Kumar if (axgbe_phy_port_mode_mismatch(pdata)) { 20244ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "phy mode/speed mismatch (%#x/%#x)\n", 20254ac7516bSRavi Kumar phy_data->port_mode, phy_data->port_speeds); 20264ac7516bSRavi Kumar return -EINVAL; 20274ac7516bSRavi Kumar } 20284ac7516bSRavi Kumar 20294ac7516bSRavi Kumar /* Check for and validate MDIO reset support */ 20304ac7516bSRavi Kumar ret = axgbe_phy_mdio_reset_setup(pdata); 20314ac7516bSRavi Kumar if (ret) 20324ac7516bSRavi Kumar return ret; 20334ac7516bSRavi Kumar 20344ac7516bSRavi Kumar /* Validate the re-driver information */ 20354ac7516bSRavi Kumar if (axgbe_phy_redrv_error(phy_data)) { 20364ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "phy re-driver settings error\n"); 20374ac7516bSRavi Kumar return -EINVAL; 20384ac7516bSRavi Kumar } 20394ac7516bSRavi Kumar pdata->kr_redrv = phy_data->redrv; 20404ac7516bSRavi Kumar 20414ac7516bSRavi Kumar /* Indicate current mode is unknown */ 20424ac7516bSRavi Kumar phy_data->cur_mode = AXGBE_MODE_UNKNOWN; 20434ac7516bSRavi Kumar 20444ac7516bSRavi Kumar /* Initialize supported features */ 20454ac7516bSRavi Kumar pdata->phy.supported = 0; 20464ac7516bSRavi Kumar 20474ac7516bSRavi Kumar switch (phy_data->port_mode) { 20484ac7516bSRavi Kumar /* Backplane support */ 20494ac7516bSRavi Kumar case AXGBE_PORT_MODE_BACKPLANE: 20504ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Autoneg; 20514ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 20524ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Backplane; 20534ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { 20544ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_1000baseKX_Full; 20554ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_KX_1000; 20564ac7516bSRavi Kumar } 20574ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) { 20584ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_10000baseKR_Full; 20594ac7516bSRavi Kumar if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) 20604ac7516bSRavi Kumar pdata->phy.supported |= 20614ac7516bSRavi Kumar SUPPORTED_10000baseR_FEC; 20624ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_KR; 20634ac7516bSRavi Kumar } 20644ac7516bSRavi Kumar 20654ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE; 20664ac7516bSRavi Kumar break; 20674ac7516bSRavi Kumar case AXGBE_PORT_MODE_BACKPLANE_2500: 20684ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 20694ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Backplane; 20704ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_2500baseX_Full; 20714ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_KX_2500; 20724ac7516bSRavi Kumar 20734ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE; 20744ac7516bSRavi Kumar break; 20754ac7516bSRavi Kumar 20764ac7516bSRavi Kumar /* MDIO 1GBase-T support */ 20774ac7516bSRavi Kumar case AXGBE_PORT_MODE_1000BASE_T: 20784ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Autoneg; 20794ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 20804ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_TP; 20814ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) { 20824ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_100baseT_Full; 20834ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_100; 20844ac7516bSRavi Kumar } 20854ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { 20864ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_1000baseT_Full; 20874ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_1000; 20884ac7516bSRavi Kumar } 20894ac7516bSRavi Kumar 20904ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_CL22; 20914ac7516bSRavi Kumar break; 20924ac7516bSRavi Kumar 20934ac7516bSRavi Kumar /* MDIO Base-X support */ 20944ac7516bSRavi Kumar case AXGBE_PORT_MODE_1000BASE_X: 20954ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Autoneg; 20964ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 20974ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_FIBRE; 20984ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_1000baseT_Full; 20994ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_X; 21004ac7516bSRavi Kumar 21014ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_CL22; 21024ac7516bSRavi Kumar break; 21034ac7516bSRavi Kumar 21044ac7516bSRavi Kumar /* MDIO NBase-T support */ 21054ac7516bSRavi Kumar case AXGBE_PORT_MODE_NBASE_T: 21064ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Autoneg; 21074ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 21084ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_TP; 21094ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) { 21104ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_100baseT_Full; 21114ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_100; 21124ac7516bSRavi Kumar } 21134ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { 21144ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_1000baseT_Full; 21154ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_1000; 21164ac7516bSRavi Kumar } 21174ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500) { 21184ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_2500baseX_Full; 21194ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_KX_2500; 21204ac7516bSRavi Kumar } 21214ac7516bSRavi Kumar 21224ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_CL45; 21234ac7516bSRavi Kumar break; 21244ac7516bSRavi Kumar 21254ac7516bSRavi Kumar /* 10GBase-T support */ 21264ac7516bSRavi Kumar case AXGBE_PORT_MODE_10GBASE_T: 21274ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Autoneg; 21284ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 21294ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_TP; 21304ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) { 21314ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_100baseT_Full; 21324ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_100; 21334ac7516bSRavi Kumar } 21344ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { 21354ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_1000baseT_Full; 21364ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_1000; 21374ac7516bSRavi Kumar } 21384ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) { 21394ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_10000baseT_Full; 21404ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_KR; 21414ac7516bSRavi Kumar } 21424ac7516bSRavi Kumar 21434ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE; 21444ac7516bSRavi Kumar break; 21454ac7516bSRavi Kumar 21464ac7516bSRavi Kumar /* 10GBase-R support */ 21474ac7516bSRavi Kumar case AXGBE_PORT_MODE_10GBASE_R: 21484ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Autoneg; 21494ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 21504ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_TP; 21514ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_10000baseT_Full; 21524ac7516bSRavi Kumar if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) 21534ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_10000baseR_FEC; 21544ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SFI; 21554ac7516bSRavi Kumar 21564ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE; 21574ac7516bSRavi Kumar break; 21584ac7516bSRavi Kumar 21594ac7516bSRavi Kumar /* SFP support */ 21604ac7516bSRavi Kumar case AXGBE_PORT_MODE_SFP: 21614ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Autoneg; 21624ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 21634ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_TP; 21644ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_FIBRE; 21654ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) { 21664ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_100baseT_Full; 21674ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_100; 21684ac7516bSRavi Kumar } 21694ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { 21704ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_1000baseT_Full; 21714ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SGMII_1000; 21724ac7516bSRavi Kumar } 21734ac7516bSRavi Kumar if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) { 21744ac7516bSRavi Kumar pdata->phy.supported |= SUPPORTED_10000baseT_Full; 21754ac7516bSRavi Kumar phy_data->start_mode = AXGBE_MODE_SFI; 21764ac7516bSRavi Kumar if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) 21774ac7516bSRavi Kumar pdata->phy.supported |= 21784ac7516bSRavi Kumar SUPPORTED_10000baseR_FEC; 21794ac7516bSRavi Kumar } 21804ac7516bSRavi Kumar 21814ac7516bSRavi Kumar phy_data->phydev_mode = AXGBE_MDIO_MODE_CL22; 21824ac7516bSRavi Kumar 21834ac7516bSRavi Kumar axgbe_phy_sfp_setup(pdata); 21844ac7516bSRavi Kumar break; 21854ac7516bSRavi Kumar default: 21864ac7516bSRavi Kumar return -EINVAL; 21874ac7516bSRavi Kumar } 21884ac7516bSRavi Kumar 21894ac7516bSRavi Kumar if ((phy_data->conn_type & AXGBE_CONN_TYPE_MDIO) && 21904ac7516bSRavi Kumar (phy_data->phydev_mode != AXGBE_MDIO_MODE_NONE)) { 21914ac7516bSRavi Kumar ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->mdio_addr, 21924ac7516bSRavi Kumar phy_data->phydev_mode); 21934ac7516bSRavi Kumar if (ret) { 21944ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "mdio port/clause not compatible (%d/%u)\n", 21954ac7516bSRavi Kumar phy_data->mdio_addr, phy_data->phydev_mode); 21964ac7516bSRavi Kumar return -EINVAL; 21974ac7516bSRavi Kumar } 21984ac7516bSRavi Kumar } 21994ac7516bSRavi Kumar 22004ac7516bSRavi Kumar if (phy_data->redrv && !phy_data->redrv_if) { 22014ac7516bSRavi Kumar ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->redrv_addr, 22024ac7516bSRavi Kumar AXGBE_MDIO_MODE_CL22); 22034ac7516bSRavi Kumar if (ret) { 22044ac7516bSRavi Kumar PMD_DRV_LOG(ERR, "redriver mdio port not compatible (%u)\n", 22054ac7516bSRavi Kumar phy_data->redrv_addr); 22064ac7516bSRavi Kumar return -EINVAL; 22074ac7516bSRavi Kumar } 22084ac7516bSRavi Kumar } 220900072056SRavi Kumar 221000072056SRavi Kumar phy_data->phy_cdr_delay = AXGBE_CDR_DELAY_INIT; 22114ac7516bSRavi Kumar return 0; 22124ac7516bSRavi Kumar } 22134ac7516bSRavi Kumar void axgbe_init_function_ptrs_phy_v2(struct axgbe_phy_if *phy_if) 22144ac7516bSRavi Kumar { 22154ac7516bSRavi Kumar struct axgbe_phy_impl_if *phy_impl = &phy_if->phy_impl; 22164ac7516bSRavi Kumar 22174ac7516bSRavi Kumar phy_impl->init = axgbe_phy_init; 2218a5c72737SRavi Kumar phy_impl->reset = axgbe_phy_reset; 2219a5c72737SRavi Kumar phy_impl->start = axgbe_phy_start; 2220a5c72737SRavi Kumar phy_impl->stop = axgbe_phy_stop; 2221a5c72737SRavi Kumar phy_impl->link_status = axgbe_phy_link_status; 2222a5c72737SRavi Kumar phy_impl->use_mode = axgbe_phy_use_mode; 2223a5c72737SRavi Kumar phy_impl->set_mode = axgbe_phy_set_mode; 2224a5c72737SRavi Kumar phy_impl->get_mode = axgbe_phy_get_mode; 2225a5c72737SRavi Kumar phy_impl->switch_mode = axgbe_phy_switch_mode; 2226a5c72737SRavi Kumar phy_impl->cur_mode = axgbe_phy_cur_mode; 2227a5c72737SRavi Kumar phy_impl->an_mode = axgbe_phy_an_mode; 2228a5c72737SRavi Kumar phy_impl->an_config = axgbe_phy_an_config; 2229a5c72737SRavi Kumar phy_impl->an_advertising = axgbe_phy_an_advertising; 2230a5c72737SRavi Kumar phy_impl->an_outcome = axgbe_phy_an_outcome; 223100072056SRavi Kumar 223200072056SRavi Kumar phy_impl->an_pre = axgbe_phy_an_pre; 223300072056SRavi Kumar phy_impl->an_post = axgbe_phy_an_post; 223400072056SRavi Kumar 223500072056SRavi Kumar phy_impl->kr_training_pre = axgbe_phy_kr_training_pre; 223600072056SRavi Kumar phy_impl->kr_training_post = axgbe_phy_kr_training_post; 22374ac7516bSRavi Kumar } 2238