phy82328.c (241121B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: phy82328.c 8 * Purpose: Phys Driver support for Broadcom 82328 40G phy 9 * Note: 10 * 11 * Specifications: 12 13 * Repeater mode only, no retimer operation. 14 15 * Supports the following data speeds: 16 * 1.25 Gbps line rate (1 GbE data rate, 8x oversampled over 10 Gbps line rate) 17 * 10.3125 Gbps line rate (10 GbE data rate) 18 * 11.5 Gpbs line rate (for backplane application, proprietary data rate) 19 * 410.3125 Gbps line rate (40 GbE data rate) 20 * 21 * Supports the following line-side connections: 22 * 1 GbE and 10 GbE SFP+ SR and LR optical modules 23 * 40 GbE QSFP SR4 and LR4 optical modules 24 * 1 GbE and 10 GbE SFP+ CR (CX1) copper cable 25 * 40 GbE QSFP CR4 copper cable 26 * 10 GbE KR, 11.5 Gbps line rate and 40 GbE KR4 backplanes 27 * 28 * Operates with the following reference clocks: 29 * Single 156.25 MHz differential clock for 1.25 Gbps, 10.3125 Gpbs and 11.5 Gbps 30 * line rates 31 * 32 * Supports autonegotiation as follows: 33 * Clause 73 only for starting Clause 72 and requesting FEC 34 * No speed resolution performed 35 * No Clause 73 in 11.5 Gbps line rate, only Clause 72 supported 36 * Clause 72 may be enabled standalone for close systems 37 * Clause 37 is not supported 38 * No on-chip FEC encoding/decoding, but shall pass-through FEC-encoded data. 39 */ 40 41 #if defined(INCLUDE_PHY_82328) /* INCLUDE_PHY_82328 */ 42 43 #include <sal/types.h> 44 #include <shared/bsl.h> 45 #include <soc/drv.h> 46 #include <soc/debug.h> 47 #include <soc/error.h> 48 #include <soc/phyreg.h> 49 50 #include <soc/phy.h> 51 #include <soc/phy/phyctrl.h> 52 #include <soc/phy/drv.h> 53 54 #include "phydefs.h" /* Must include before other phy related includes */ 55 #include "phyconfig.h" /* Must be the first phy include after phydefs.h */ 56 #include "phyident.h" 57 #include "phyreg.h" 58 #include "phynull.h" 59 #include "phyxehg.h" 60 #include "phy82328.h" 61 extern unsigned char phy82328_ucode_bin[]; 62 extern unsigned int phy82328_ucode_bin_len; 63 static char *dev_name_82328_a0 = "BCM82328_A0"; 64 static char *dev_name_82328f_a0 = "BCM82328F_A0"; 65 66 extern unsigned char phy82328B0_ucode_bin[]; 67 extern unsigned int phy82328B0_ucode_bin_len; 68 static char *dev_name_82328_b0 = "BCM82328_B0"; 69 static char *dev_name_82322_b1 = "BCM82322_B1"; 70 static char *dev_name_82328_b1 = "BCM82328_B1"; 71 static char *dev_name_82328f_b0 = "BCM82328F_B0"; 72 static char *dev_name_82328f_b1 = "BCM82328F_B1"; 73 #define PHY82328B1_CHIP_REV (0x00b1) 74 #define PHY82328B0_CHIP_REV (0x00b0) 75 #define PHY82328A0_CHIP_REV (0x00a0) 76 static char *dev_name_82322 = "BCM82322"; 77 #define PHY82328_DEV_PMA_PMD 1 78 #define PHY82328_DEV_AN 2 79 #define PHY82328_ENABLE 1 80 #define PHY82328_DISABLE 0 81 #define PHY82328_TOTAL_WR_BYTE 0x4000 82 #define PHY82328_ID_82328 0x82328 /* Gallardo_28nm_oct_opt */ 83 #define PHY82328_ID_82328F 0x8232f /* Gallardo_28nm_oct_opt */ 84 #define PHY82328_ID_82322 0x82322 /* Gallardo_28nm_oct_opt */ 85 #define PHY82328_NUM_LANES 4 86 #define PHY82328_20G_NUM_LANES 2 87 #define PHY82328_ALL_LANES 0xf 88 #define PHY82328_POL_DND 0xFFFF 89 #define PHY82328_SPD_1G 1000 90 #define PHY82328_SPD_10G 10000 91 #define PHY82328_SPD_11G 11000 92 #define PHY82328_SPD_40G 40000 93 #define PHY82328_SPD_20G 20000 94 #define PHY82328_SPD_42G 42000 95 #define PHY82328_SPD_100G 100000 96 #define PHY82328_GP_REG_1_SPD_100G (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_100G_SHIFT) 97 #define PHY82328_GP_REG_1_SPD_42G ((1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_40G_SHIFT)| \ 98 (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_10G_SHIFT) | \ 99 (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_1G_SHIFT)) 100 #define PHY82328_GP_REG_1_SPD_40G (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_40G_SHIFT) 101 #define PHY82328_GP_REG_1_SPD_11G ((1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_40G_SHIFT)| \ 102 (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_1G_SHIFT)) 103 #define PHY82328_GP_REG_1_SPD_10G (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_10G_SHIFT) 104 #define PHY82328_GP_REG_1_SPD_1G ((1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_1G_SHIFT) | \ 105 (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_10G_SHIFT)) 106 107 #define PHY82328_4BIT_DP_DEPTH1 (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_ENABLE_ULTRA_LOW_LATENCY_DATAPATH_SHIFT) 108 #define PHY82328_4BIT_DP_DEPTH2 ((1 << MGT_TOP_PMD_USR_GP_REGISTER_1_ENABLE_ULTRA_LOW_LATENCY_DATAPATH_SHIFT) | \ 109 (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_ULL_DATAPATH_LATENCY_SHIFT)) 110 111 #define PHY82328_SINGLE_PORT_MODE(_pc) \ 112 (SOC_INFO((_pc)->unit).port_num_lanes[(_pc)->port] >= 4) 113 114 #define PHY82328_AN_CTRL_REG 0x0000 115 #define PHY82328_AN_STS_REG 0x0001 116 #define PHY82328_AN_STS_LINK_STS_MSK 0x0004 117 #define PHY82328_AN_ENABLE_MSK (1<<12) 118 #define PHY82328_AN_COMPLETE_MSK (1<<5) 119 120 /* I2C related defines */ 121 #define PHY82328_BSC_XFER_MAX 0x1F9 122 #define PHY82328_BSC_WR_MAX 16 123 #define PHY82328_WRITE_START_ADDR 0x8007 124 #define PHY82328_READ_START_ADDR 0x8007 125 #define PHY82328_WR_FREQ_400KHZ 0x0100 126 #define PHY82328_2W_STAT 0x000C 127 #define PHY82328_2W_STAT_IDLE 0x0000 128 #define PHY82328_2W_STAT_COMPLETE 0x0004 129 #define PHY82328_2W_STAT_IN_PRG 0x0008 130 #define PHY82328_2W_STAT_FAIL 0x000C 131 #define PHY82328_BSC_WRITE_OP 0x22 132 #define PHY82328_BSC_READ_OP 0x2 133 #define PHY82328_I2CDEV_WRITE 0x1 134 #define PHY82328_I2CDEV_READ 0x0 135 #define PHY82328_I2C_8BIT 0 136 #define PHY82328_I2C_16BIT 1 137 #define PHY82328_I2C_TEMP_RAM 0xE 138 #define PHY82328_I2C_OP_TYPE(access_type,data_type) \ 139 ((access_type) | ((data_type) << 8)) 140 #define PHY82328_I2C_ACCESS_TYPE(op_type) ((op_type) & 0xff) 141 #define PHY82328_I2C_DATA_TYPE(op_type) (((op_type) >> 8) & 0xff) 142 #define PHY82328_I2CM_IDLE_WAIT_MSEC 350 143 #define PHY82328_I2CM_IDLE_WAIT_CHUNK 10 144 #define PHY82328_I2CM_IDLE_WAIT_COUNT (PHY82328_I2CM_IDLE_WAIT_MSEC / PHY82328_I2CM_IDLE_WAIT_CHUNK) 145 146 #define PHY82328_PREEMPHASIS_LANE_GET(_T, _L) \ 147 if (_T == SOC_PHY_CONTROL_PREEMPHASIS_LANE0) { \ 148 _L = 0; } \ 149 else if (_T == SOC_PHY_CONTROL_PREEMPHASIS_LANE1) { \ 150 _L = 1; } \ 151 else if (_T == SOC_PHY_CONTROL_PREEMPHASIS_LANE2) { \ 152 _L = 2; } \ 153 else if (_T == SOC_PHY_CONTROL_PREEMPHASIS_LANE3) { \ 154 _L = 3; } \ 155 else { \ 156 _L = PHY82328_ALL_LANES; } 157 158 159 static const char *phy82328_intf_names[] = SOC_PORT_IF_NAMES_INITIALIZER; 160 int eye_consol_val[64][64]; 161 162 /* interface params */ 163 typedef struct phy82328_intf_cfg { 164 int32 speed; 165 soc_port_if_t type; 166 } phy82328_intf_cfg_t; 167 168 typedef enum { 169 PHY82328_DATAPATH_20, 170 PHY82328_DATAPATH_4_DEPTH_1, 171 PHY82328_DATAPATH_4_DEPTH_2 172 }phy82328_datapath_t; 173 174 typedef enum { 175 PHY82328_INTF_SIDE_LINE, 176 PHY82328_INTF_SIDE_SYS 177 } phy82328_intf_side_t; 178 179 typedef struct { 180 int32 enable; 181 int32 count; /* resume only if count==0 */ 182 } phy82328_micro_ctrl_t; 183 184 typedef struct { 185 uint32 devid; 186 uint32 devrev; 187 int32 p2l_map[PHY82328_NUM_LANES]; /* index: physical lane, array element: */ 188 phy82328_intf_cfg_t line_intf; 189 phy82328_intf_cfg_t sys_intf; 190 uint16 pol_tx_cfg; 191 uint16 pol_rx_cfg; 192 int32 mod_auto_detect; /* module auto detect enabled */ 193 phy82328_datapath_t cfg_datapath; 194 phy82328_datapath_t cur_datapath; 195 int32 an_en; 196 uint16 logical_lane0; 197 int32 sys_forced_cl72; 198 int32 sync_init; 199 phy82328_micro_ctrl_t micro_ctrl; 200 int32 fw_rx_los; 201 int32 int_phy_re_en; 202 soc_timeout_t sync_to; 203 int cfg_sys_intf; 204 uint16 port_disabled; 205 } phy82328_dev_desc_t; 206 207 #define DEVID(_pc) (((phy82328_dev_desc_t *)((_pc) + 1))->devid) 208 #define DEVREV(_pc) (((phy82328_dev_desc_t *)((_pc) + 1))->devrev) 209 #define P2L_MAP(_pc,_ix) (((phy82328_dev_desc_t *)((_pc) + 1))->p2l_map[(_ix)]) 210 #define LINE_INTF(_pc) (((phy82328_dev_desc_t *)((_pc) + 1))->line_intf) 211 #define SYS_INTF(_pc) (((phy82328_dev_desc_t *)((_pc) + 1))->sys_intf) 212 #define POL_TX_CFG(_pc) (((phy82328_dev_desc_t *)((_pc) + 1))->pol_tx_cfg) 213 #define POL_RX_CFG(_pc) (((phy82328_dev_desc_t *)((_pc) + 1))->pol_rx_cfg) 214 #define MOD_AUTO_DETECT(_pc) (((phy82328_dev_desc_t *)((_pc) + 1))->mod_auto_detect) 215 #define CFG_DATAPATH(_pc) (((phy82328_dev_desc_t *)((_pc) + 1))->cfg_datapath) 216 #define CUR_DATAPATH(_pc) (((phy82328_dev_desc_t *)((_pc) + 1))->cur_datapath) 217 #define AN_EN(_pc) (((phy82328_dev_desc_t *)((_pc) + 1))->an_en) 218 #define SYS_FORCED_CL72(_pc) (((phy82328_dev_desc_t *)((_pc) + 1))->sys_forced_cl72) 219 #define SYNC_INIT(_pc) (((phy82328_dev_desc_t *)((_pc) + 1))->sync_init) 220 #define MICRO_CTRL(_pc) (((phy82328_dev_desc_t *)((_pc) + 1))->micro_ctrl) 221 #define FW_RX_LOS(_pc) (((phy82328_dev_desc_t *)((_pc) + 1))->fw_rx_los) 222 #define LOGICAL_LANE0(_pc) (((phy82328_dev_desc_t *)((_pc) + 1))->logical_lane0) 223 #define SYNC_TO(_pc) (((phy82328_dev_desc_t *)((_pc) + 1))->sync_to) 224 #define INT_PHY_RE_EN(_pc) (((phy82328_dev_desc_t *)((_pc) + 1))->int_phy_re_en) 225 #define CFG_SYS_INTF(_pc) (((phy82328_dev_desc_t *)((_pc) + 1))->cfg_sys_intf) 226 #define PORT_DISABLED(_pc) (((phy82328_dev_desc_t *)((_pc) + 1))->port_disabled) 227 228 229 #define PHY_82328_MICRO_PAUSE(_u, _p, _s) \ 230 do { \ 231 phy_ctrl_t *_pc; \ 232 _pc = EXT_PHY_SW_STATE((_u), (_p)); \ 233 if (DEVREV(_pc) == PHY82328A0_CHIP_REV || DEVREV(_pc) == PHY82328B0_CHIP_REV || DEVREV(_pc) == PHY82328B1_CHIP_REV) { \ 234 _phy_82328_micro_pause((_u), (_p), (_s)); \ 235 } \ 236 } while (0) 237 238 #define PHY_82328_MICRO_RESUME(_u, _p)\ 239 do { \ 240 phy_ctrl_t *_pc; \ 241 _pc = EXT_PHY_SW_STATE((_u), (_p)); \ 242 if (DEVREV(_pc) == PHY82328A0_CHIP_REV || DEVREV(_pc) == PHY82328B0_CHIP_REV || DEVREV(_pc) == PHY82328B1_CHIP_REV) { \ 243 _phy_82328_micro_resume((_u), (_p)); \ 244 } \ 245 } while (0) 246 247 #define POL_CONFIG_LANE_MASK(_l) (1 << _l) 248 249 /* QSFI_RX :: anaRxStatus :: status_sel [02:00] */ 250 #define QSFI_RX_ANARXSTATUS_SM_SEL_MASK 0x0007 251 252 /* QSFI_RX :: anaRxStatus :: status_sel [02:00] */ 253 #define QSFI_RX_ANARXSTATUS_PMD_RX_PMD_LOCK_MASK 0x1000 254 255 /* REMOTE PHY ABLITY REG*/ 256 #define PHY82328_RMT_PHY_ABLITY_REG 0xc450 257 258 /* REMOTE PHY VALID FLAG*/ 259 #define PHY82328_RMT_PHY_ABLITY_VALID_MASK 0x8 260 #define PHY82328_RMT_PHY_ABLITY_KR_MASK 0x10 261 #define PHY82328_RMT_PHY_ABLITY_KR2_MASK 0x20 262 #define PHY82328_RMT_PHY_ABLITY_KR4_MASK 0x40 263 #define PHY82328_RMT_PHY_ABLITY_PAUSE_MASK 0x3800 264 #define PHY82328_RMT_PHY_ABLITY_FEC_MASK 0xC000 265 266 /* EYE SCAN RELATED MACROS & ENUMS*/ 267 #define PHY82328_STS_IS_MICRO_STOPPED(u, p, pc, sts) phy82328_serdes_rdbl_uc_var(u, p, pc, 0x11, &sts) 268 #define PHY82328_TRNSUM_TAP_5_TO_N2 0 269 #define PHY82328_TRNSUM_TAP_0 4 270 #define PHY82328_DSC_STATE_UC_TUNE 7 271 #define PHY82328_RD_UC_DSC_RDY_FOR_CMD(u, pc, rdy) \ 272 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(u, pc, DSC_A_DSC_UC_CTRL, &rdy)); \ 273 rdy = (rdy & 0x0080) >> 7; 274 275 /** SERDES_PMD_UC_COMMANDS Enum */ 276 typedef enum PHY82328_SERDES_PMD_UC_CMD { 277 PHY82328_CMD_NULL = 0, 278 PHY82328_CMD_UC_CTRL = 1, 279 PHY82328_CMD_HEYE_OFFSET = 2, 280 PHY82328_CMD_VEYE_OFFSET = 3, 281 PHY82328_CMD_FREEZE_STEADY_STATE = 4, 282 PHY82328_CMD_DIAG_EN = 5, 283 PHY82328_CMD_READ_UC_LANE_BYTE = 6, 284 PHY82328_CMD_WRITE_UC_LANE_BYTE = 7, 285 PHY82328_CMD_READ_UC_CORE_BYTE = 8, 286 PHY82328_CMD_WRITE_UC_CORE_BYTE = 9, 287 PHY82328_CMD_READ_UC_LANE_WORD = 10, 288 PHY82328_CMD_WRITE_UC_LANE_WORD = 11, 289 PHY82328_CMD_READ_UC_CORE_WORD = 12, 290 PHY82328_CMD_WRITE_UC_CORE_WORD = 13, 291 PHY82328_CMD_EVENT_LOG_CTRL = 14, 292 PHY82328_CMD_EVENT_LOG_READ = 15 293 }PHY82328_SERDES_PMD_UC_CMD; 294 295 /** SERDES_UC_CTRL_COMMANDS Enum */ 296 typedef enum PHY82328_SERDES_PMD_UC_CTRL_CMD { 297 PHY82328_CMD_UC_CTRL_STOP_GRACEFULLY = 0, 298 PHY82328_CMD_UC_CTRL_STOP_IMMEDIATE = 1, 299 PHY82328_CMD_UC_CTRL_RESUME = 2, 300 PHY82328_CMD_UC_CTRL_STOP_HOLD = 3, 301 PHY82328_CMD_UC_CTRL_RELEASE_HOLD_ONCE = 4 302 }PHY82328_SERDES_PMD_UC_CTRL_CMD; 303 304 typedef enum PHY82328_TRNSUM_ERR_SEL { 305 PHY82328_TRNSUM_ERR_SEL_EMUX = 0, 306 PHY82328_TRNSUM_ERR_SEL_1 = 1, 307 PHY82328_TRNSUM_ERR_SEL_M1 = 2, 308 PHY82328_TRNSUM_ERR_SEL_P1 = 3 309 }PHY82328_TRNSUM_ERR_SEL; 310 311 soc_port_if_t phy82328_sys_to_port_if[] = { 312 0, /* PHY_SYSTEM_INTERFACE_DFLT */ 313 SOC_PORT_IF_KX, /* PHY_SYSTEM_INTERFACE_KX */ 314 SOC_PORT_IF_KR, /* PHY_SYSTEM_INTERFACE_KR */ 315 SOC_PORT_IF_SR, /* PHY_SYSTEM_INTERFACE_SR */ 316 SOC_PORT_IF_LR, /* PHY_SYSTEM_INTERFACE_LR */ 317 SOC_PORT_IF_CR, /* PHY_SYSTEM_INTERFACE_CR */ 318 SOC_PORT_IF_KR4, /* PHY_SYSTEM_INTERFACE_KR4 */ 319 SOC_PORT_IF_SR4, /* PHY_SYSTEM_INTERFACE_SR4 */ 320 SOC_PORT_IF_LR4, /* PHY_SYSTEM_INTERFACE_LR4 */ 321 SOC_PORT_IF_CR4, /* PHY_SYSTEM_INTERFACE_CR4 */ 322 SOC_PORT_IF_XFI, /* PHY_SYSTEM_INTERFACE_XFI */ 323 SOC_PORT_IF_XLAUI, /* PHY_SYSTEM_INTERFACE_XLAUI */ 324 325 }; 326 327 #ifdef PHY82328_MDIO_DEBUGGING 328 #undef READ_PHY_REG 329 #define READ_PHY_REG(_unit, _pc, _addr, _value) \ 330 ((_phy_82328_dbg_read)((_pc->unit), _pc, (_addr), (_value))) 331 #undef WRITE_PHY_REG 332 #define WRITE_PHY_REG(_unit, _pc, _addr, _value) \ 333 ((_phy_82328_dbg_write)((_pc->unit), _pc, (_addr), (_value))) 334 #undef MODIFY_PHY_REG 335 #define MODIFY_PHY_REG(_unit, _pc, _addr, _data, _mask) \ 336 (_phy_82328_dbg_modify((_unit), (_pc), (_addr), (_data), (_mask))) 337 #endif 338 339 /* dsc values */ 340 typedef struct { 341 uint8 osr_mode; 342 uint16 ucv_config; 343 uint8 sig_det; 344 uint8 rx_lock; 345 int16 rx_ppm; 346 int8 clk90; 347 int8 clkp1; 348 uint8 pf_main; 349 uint8 pf_hiz; 350 uint8 pf_bst; 351 uint8 pf_low; 352 uint8 vga; 353 int8 dc_offset; 354 uint8 p1_lvl_ctrl; 355 uint8 dfe1; 356 int8 dfe2; 357 int8 dfe3; 358 int8 dfe4; 359 int8 dfe5; 360 int8 dfe1_dcd; 361 int8 dfe2_dcd; 362 int8 pe; 363 int8 ze; 364 int8 me; 365 int8 po; 366 int8 zo; 367 int8 mo; 368 uint8 tx_ppm; 369 uint8 txfir_pre; 370 uint8 txfir_main; 371 uint8 txfir_post1; 372 uint8 txfir_post2; 373 uint8 heye_left; 374 uint8 heye_right; 375 uint8 veye_upper; 376 uint8 veye_lower; 377 uint8 br_pd_en; 378 } phy82328_serdes_lane_state; 379 380 #define PHY82328_CONV_SIGNED_BYTE(_D, _M, _L) \ 381 _D <<= (15 - (_M)); \ 382 _D >>= (15 - (_M) + (_L)); \ 383 _D &= (0xFF); 384 385 386 STATIC int32 387 _phy_82328_channel_select(int32 unit, soc_port_t port, phy82328_intf_side_t side, int32 lane); 388 STATIC int32 389 _phy_82328_polarity_flip(int32 unit, soc_port_t port, uint16 cfg_tx_pol, uint16 cfg_rx_pol); 390 STATIC int32 391 phy_82328_control_get(int32 unit, soc_port_t port, 392 soc_phy_control_t type, uint32 *value); 393 STATIC int32 394 phy_82328_control_set(int32 unit, soc_port_t port, 395 soc_phy_control_t type, uint32 value); 396 STATIC void 397 _phy_82328_micro_pause(int32 unit, soc_port_t port, const char *loc); 398 STATIC void 399 _phy_82328_micro_resume(int32 unit, soc_port_t port); 400 STATIC int32 401 _phy_82328_debug_info(int32 unit, soc_port_t port); 402 STATIC int32 403 _phy_82328_intf_line_sys_init(int32 unit, soc_port_t port); 404 STATIC int32 405 _phy_82328_intf_type_set(int32 unit, soc_port_t port, soc_port_if_t pif, int32 must_update); 406 STATIC int32 407 phy_82328_an_get(int32 unit, soc_port_t port, int32 *an, int32 *an_done); 408 STATIC int32 409 _phy_82328_intf_line_sys_update(int32 unit, soc_port_t port); 410 411 STATIC int32 412 _phy_82328_speed_set(int32 unit, soc_port_t port, int32 speed); 413 414 STATIC int32 415 phy_82328_regbit_set_wait_check(int32 unit ,int32 port, 416 int32 reg, int32 bit_num, 417 int32 bitset, int32 timeout); 418 STATIC int32 419 _phy_82328_rx_los_control_set(int32 unit, soc_port_t port, uint32 value); 420 421 422 #ifdef PHY82328_MDIO_DEBUGGING 423 STATIC int32 424 _phy_82328_dbg_read(int32 unit, phy_ctrl_t *pc, uint32 addr, uint16 *data) 425 { 426 int32 rv; 427 rv = (pc->read)(unit, pc->phy_id, addr, data); 428 429 LOG_INFO(BSL_LS_SOC_PHY, 430 (BSL_META_U(unit, 431 "Read Addr=0x%04x Val=0x%04x\n"), addr, *data)); 432 return rv; 433 434 } 435 436 STATIC int32 437 _phy_82328_dbg_write(int32 unit, phy_ctrl_t *pc, uint32 addr, uint16 data) 438 { 439 int32 rv; 440 LOG_INFO(BSL_LS_SOC_PHY, 441 (BSL_META_U(unit, 442 "Write Addr=0x%04x Val=0x%04x\n"), addr, data)); 443 rv = (pc->write)(unit, pc->phy_id, addr, data); 444 return rv; 445 } 446 447 STATIC int32 448 _phy_82328_dbg_modify(int32 unit, phy_ctrl_t *pc, uint32 addr, uint16 data, uint16 mask) 449 { 450 int32 rv; 451 rv = phy_reg_modify(unit, pc, addr, data, mask); 452 rv = (pc->read)(unit, pc->phy_id, addr, &data); 453 LOG_INFO(BSL_LS_SOC_PHY, 454 (BSL_META_U(unit, 455 "Write Addr=0x%04x Val=0x%04x\n"), addr, data)); 456 return rv; 457 } 458 #endif 459 460 STATIC 461 int32 phy82328_intf_side_reg_select(int unit, soc_port_t port, uint16 intf) 462 { 463 phy_ctrl_t *pc; 464 pc = EXT_PHY_SW_STATE(unit, port); 465 466 SOC_IF_ERROR_RETURN 467 (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_XPMD_REGS_SEL, intf)); 468 return SOC_E_NONE; 469 } 470 471 STATIC 472 int32 _phy_82328_modify_pma_pmd_reg (int32 unit, int32 port, phy_ctrl_t *pc, 473 uint16 dev, uint16 address, uint8 msb_pos, 474 uint8 lsb_pos, uint16 data) 475 { 476 uint16 mask = 0, i =0; 477 478 for (i = lsb_pos; i<=msb_pos; i++) { 479 mask |= (1 << i); 480 } 481 482 data = data << lsb_pos; 483 if (dev == PHY82328_DEV_PMA_PMD) { 484 SOC_IF_ERROR_RETURN 485 (MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, address, 486 data, mask)); 487 } else { 488 SOC_IF_ERROR_RETURN 489 (MODIFY_PHY82328_MMF_AN_REG(unit, pc, address, 490 data, mask)); 491 } 492 return SOC_E_NONE; 493 } 494 495 STATIC 496 int32 _phy_82328_set_bcast_mode(int32 unit, int32 port, 497 int16 ena_dis) 498 { 499 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 500 501 SOC_IF_ERROR_RETURN 502 (_phy_82328_modify_pma_pmd_reg (unit, port, pc, 503 PHY82328_DEV_PMA_PMD, MGT_TOP_BROADCAST_CTRL, 504 MGT_TOP_PMD_USR_BROADCAST_CTRL_BROADCAST_MODE_ENABLE_SHIFT, 505 MGT_TOP_PMD_USR_BROADCAST_CTRL_BROADCAST_MODE_ENABLE_SHIFT, ena_dis)); 506 507 return SOC_E_NONE; 508 } 509 510 STATIC 511 int32 _phy_82328_soft_reset(int32 unit, int32 port) 512 { 513 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 514 515 SOC_IF_ERROR_RETURN 516 (_phy_82328_modify_pma_pmd_reg (unit, port, pc, 517 PHY82328_DEV_PMA_PMD, IEEE0_BLK_PMA_PMD_PMD_CONTROL_REGISTER, 518 QSFI_IEEE0_PMD_CONTROL_REGISTER_RESET_SHIFT, 519 QSFI_IEEE0_PMD_CONTROL_REGISTER_RESET_SHIFT, 1)); 520 521 return SOC_E_NONE; 522 } 523 524 STATIC 525 int32 _phy_82328_rom_fw_dload (int32 unit, int32 port, int32 offset, 526 uint8 *new_fw, uint32 datalen) 527 { 528 uint32 wr_data = 0, j = 0; 529 uint16 data16 = 0, temp = 0; 530 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 531 if (offset == PHYCTRL_UCODE_BCST_SETUP) { 532 /* Enable Bcast */ 533 LOG_INFO(BSL_LS_SOC_PHY, 534 (BSL_META_U(unit, 535 "PHY82328 Enable Bcast u:%d p:%d\n"), 536 unit, port)); 537 SOC_IF_ERROR_RETURN (_phy_82328_set_bcast_mode(unit, port, 538 PHY82328_ENABLE)); 539 return SOC_E_NONE; 540 } else if (offset == PHYCTRL_UCODE_BCST_uC_SETUP) { 541 LOG_INFO(BSL_LS_SOC_PHY, 542 (BSL_META_U(unit, 543 "PHY82328 uC setup u:%d p:%d\n"), 544 unit, port)); 545 546 /* uController reset */ 547 SOC_IF_ERROR_RETURN 548 (_phy_82328_modify_pma_pmd_reg (unit, port, pc, 549 PHY82328_DEV_PMA_PMD, MGT_TOP_GEN_CTRL, 550 MGT_TOP_CMN_CTLR_GEN_CTRL_UCRST_SHIFT, 551 MGT_TOP_CMN_CTLR_GEN_CTRL_UCRST_SHIFT, PHY82328_ENABLE)); 552 553 SOC_IF_ERROR_RETURN(_phy_82328_soft_reset(unit, port)); 554 sal_udelay(3000); 555 return SOC_E_NONE; 556 } else if (offset == PHYCTRL_UCODE_BCST_ENABLE) { 557 /* Re Enable Bcast */ 558 SOC_IF_ERROR_RETURN (_phy_82328_set_bcast_mode(unit, port, 559 PHY82328_ENABLE)); 560 return SOC_E_NONE; 561 } else if (offset == PHYCTRL_UCODE_BCST_LOAD) { 562 LOG_INFO(BSL_LS_SOC_PHY, 563 (BSL_META_U(unit, 564 "PHY82328 uCode load u:%d p:%d\n"), 565 unit, port)); 566 567 /*Select MDIO FOR ucontroller download */ 568 SOC_IF_ERROR_RETURN 569 (_phy_82328_modify_pma_pmd_reg (unit, port, pc, 570 PHY82328_DEV_PMA_PMD, MGT_TOP_SPA_CONTROL_STATUS_REGISTER, 571 MGT_TOP_PMD_USR_SPA_CONTROL_STATUS_REGISTER_SPI_PORT_USED_SHIFT, 572 MGT_TOP_PMD_USR_SPA_CONTROL_STATUS_REGISTER_SPI_PORT_USED_SHIFT, 573 PHY82328_DISABLE)); 574 575 /* Clear Download Done */ 576 SOC_IF_ERROR_RETURN 577 (_phy_82328_modify_pma_pmd_reg (unit, port, pc, 578 PHY82328_DEV_PMA_PMD, MGT_TOP_SPA_CONTROL_STATUS_REGISTER, 579 MGT_TOP_PMD_USR_SPA_CONTROL_STATUS_REGISTER_SPI_DWLD_DONE_SHIFT, 580 MGT_TOP_PMD_USR_SPA_CONTROL_STATUS_REGISTER_SPI_DWLD_DONE_SHIFT, 581 PHY82328_DISABLE)); 582 583 SOC_IF_ERROR_RETURN 584 (_phy_82328_modify_pma_pmd_reg (unit, port, pc, 585 PHY82328_DEV_PMA_PMD, MGT_TOP_SPA_CONTROL_STATUS_REGISTER, 586 MGT_TOP_PMD_USR_SPA_CONTROL_STATUS_REGISTER_SPI_BOOT_SHIFT, 587 MGT_TOP_PMD_USR_SPA_CONTROL_STATUS_REGISTER_SPI_BOOT_SHIFT, 588 PHY82328_ENABLE)); 589 590 591 /* Set Dload size to 32K */ 592 SOC_IF_ERROR_RETURN 593 (_phy_82328_modify_pma_pmd_reg (unit, port, pc, 594 PHY82328_DEV_PMA_PMD, MGT_TOP_MISC_CTRL, 595 MGT_TOP_CMN_CTLR_MISC_CTRL_SPI_DOWNLOAD_SIZE_SHIFT, 596 MGT_TOP_CMN_CTLR_MISC_CTRL_SPI_DOWNLOAD_SIZE_SHIFT, 597 PHY82328_ENABLE)); 598 599 /* uController reset */ 600 SOC_IF_ERROR_RETURN 601 (_phy_82328_modify_pma_pmd_reg (unit, port, pc, 602 PHY82328_DEV_PMA_PMD, MGT_TOP_GEN_CTRL, 603 MGT_TOP_CMN_CTLR_GEN_CTRL_UCRST_SHIFT, 604 MGT_TOP_CMN_CTLR_GEN_CTRL_UCRST_SHIFT, PHY82328_DISABLE)); 605 606 sal_udelay(3000); /*wait for 3ms to initialize the RAM*/ 607 608 /*Write Address*/ 609 SOC_IF_ERROR_RETURN 610 (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_MSG_IN, 0x8000)); 611 612 /* Make sure Address word is read by the Micro*/ 613 sal_udelay(10); 614 615 wr_data = (datalen/2); /*16k ROM*/ 616 SOC_IF_ERROR_RETURN 617 (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_MSG_IN, wr_data)); 618 sal_udelay(10); 619 620 /* Fill in the SRAM */ 621 wr_data = (datalen - 1); 622 for (j = 0; j < wr_data; j+=2) { 623 /*Make sure the word is read by the Micro */ 624 sal_udelay(10); 625 data16 = (new_fw[j] << 8) | new_fw[j+1]; 626 SOC_IF_ERROR_RETURN 627 (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_MSG_IN, data16)); 628 } 629 return SOC_E_NONE; 630 } else if(offset== PHYCTRL_UCODE_BCST_END) { 631 int i = 0; 632 sal_udelay(20); 633 if ((pc->phy_id & 3) != 0) { 634 return SOC_E_NONE; 635 } 636 temp = pc->phy_id; 637 for (i = 0; i <= 3; i++) { 638 pc->phy_id &= ~3; 639 pc->phy_id |= i; 640 SOC_IF_ERROR_RETURN 641 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_MSG_OUT, &data16)); 642 643 LOG_INFO(BSL_LS_SOC_PHY, 644 (BSL_META_U(unit, 645 "PHY82328 FW load done u:%d p:%d Read Done:0x%x\n"), 646 unit, port, data16)); 647 648 sal_udelay(4000); 649 SOC_IF_ERROR_RETURN 650 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REG_4, &data16)); 651 652 LOG_INFO(BSL_LS_SOC_PHY, 653 (BSL_META_U(unit, 654 "PHY82328 FW load done u:%d p:%d chksum:0x%x\n"), 655 unit, port, data16)); 656 657 if (data16 != 0x600D) { 658 LOG_ERROR(BSL_LS_SOC_PHY, 659 (BSL_META_U(unit, 660 "Invalid Checksum:0x%x\n"), data16)); 661 pc->phy_id = temp; 662 /* Disable Bcast */ 663 SOC_IF_ERROR_RETURN (_phy_82328_set_bcast_mode(unit, port, 664 PHY82328_DISABLE)); 665 return SOC_E_INTERNAL; 666 } 667 /*Check the register to read*/ 668 SOC_IF_ERROR_RETURN 669 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 0xc161, &data16)); 670 671 LOG_CLI((BSL_META_U(unit, 672 "PHY82328 u:%d p:%d Rom Version(Reg:0xc161):0x%x\n"), 673 unit, port, (data16 & 0xFF))); 674 675 /* Disable Bcast */ 676 SOC_IF_ERROR_RETURN (_phy_82328_set_bcast_mode(unit, port, 677 PHY82328_DISABLE)); 678 679 data16 = (PHY82328_SINGLE_PORT_MODE(pc)) ? 680 MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_SINGLE_PMD_MODE_MASK : 0; 681 SOC_IF_ERROR_RETURN 682 (MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 683 MGT_TOP_SINGLE_PMD_CTRL, data16, 684 MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_SINGLE_PMD_MODE_MASK)); 685 pc->phy_id = temp; 686 if (PHY82328_SINGLE_PORT_MODE(pc)) { 687 break; 688 } 689 /* Make sure micro completes its initialization */ 690 sal_udelay(5000); 691 } 692 pc->phy_id = temp; 693 } else { 694 LOG_ERROR(BSL_LS_SOC_PHY, 695 (BSL_META_U(unit, 696 "u=%d p=%d PHY82328 firmware_bcst: invalid cmd 0x%x\n"), 697 unit, port, offset)); 698 } 699 return SOC_E_NONE; 700 } 701 702 STATIC int32 703 _phy_82328_intf_is_single_port(soc_port_if_t intf_type) 704 { 705 int32 rv; 706 707 switch (intf_type) { 708 case SOC_PORT_IF_CR4: 709 case SOC_PORT_IF_KR4: 710 case SOC_PORT_IF_XLAUI: 711 case SOC_PORT_IF_LR4: 712 case SOC_PORT_IF_SR4: 713 rv = TRUE; 714 break; 715 default: 716 rv = FALSE; 717 } 718 return rv; 719 } 720 721 STATIC int32 722 _phy_82328_intf_is_quad_port(soc_port_if_t intf_type) 723 { 724 int32 rv; 725 726 switch (intf_type) { 727 case SOC_PORT_IF_SR: 728 case SOC_PORT_IF_CR: 729 case SOC_PORT_IF_KR: 730 case SOC_PORT_IF_XFI: 731 case SOC_PORT_IF_SFI: 732 case SOC_PORT_IF_LR: 733 case SOC_PORT_IF_ZR: 734 case SOC_PORT_IF_KX: 735 case SOC_PORT_IF_GMII: 736 case SOC_PORT_IF_SGMII: 737 rv = TRUE; 738 break; 739 default: 740 rv = FALSE; 741 } 742 return rv; 743 } 744 745 STATIC int32 746 _phy_82328_intf_line_sys_params_get(int32 unit, soc_port_t port) 747 { 748 phy82328_intf_cfg_t *line_intf; 749 phy82328_intf_cfg_t *sys_intf; 750 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 751 752 line_intf = &(LINE_INTF(pc)); 753 sys_intf = &(SYS_INTF(pc)); 754 755 /* 756 * system side interface was specified so make sure it's compatible with 757 * line side speed. If not, overwrite with default compatible interface 758 */ 759 if (line_intf->speed == PHY82328_SPD_40G) { 760 sys_intf->speed = PHY82328_SPD_40G; 761 line_intf->type = SOC_PORT_IF_SR4; 762 if (!(_phy_82328_intf_is_single_port(sys_intf->type))) { 763 /* system side interface is not compatible so overwrite with default */ 764 LOG_ERROR(BSL_LS_SOC_PHY, 765 (BSL_META_U(unit, 766 "PHY82328 incompatible 40G system side interface, " 767 "using default: u=%d p=%d\n"), unit, port)); 768 sys_intf->type = SOC_PORT_IF_XLAUI; 769 } 770 } 771 else { /* 10G/1G */ 772 if (_phy_82328_intf_is_quad_port(sys_intf->type)) { 773 if (sys_intf->type == SOC_PORT_IF_KX) { 774 line_intf->speed = PHY82328_SPD_1G; 775 line_intf->type = SOC_PORT_IF_GMII; 776 sys_intf->speed = PHY82328_SPD_1G; 777 } else { 778 /* 10G system side so fix line side to be 10G compatible */ 779 line_intf->speed = PHY82328_SPD_10G; 780 line_intf->type = SOC_PORT_IF_SR; 781 sys_intf->speed = PHY82328_SPD_10G; 782 } 783 } else { 784 /* system side interface is not compatible so overwrite with default */ 785 LOG_ERROR(BSL_LS_SOC_PHY, 786 (BSL_META_U(unit, 787 "PHY82328 incompatible 10G/1G system side interface, " 788 "using default: u=%d p=%d\n"), unit, port)); 789 /* default to 10G interface/speed on both sides */ 790 line_intf->speed = PHY82328_SPD_10G; 791 line_intf->type = SOC_PORT_IF_SR; 792 sys_intf->speed = PHY82328_SPD_10G; 793 sys_intf->type = SOC_PORT_IF_XFI; 794 } 795 } 796 return SOC_E_NONE; 797 } 798 799 STATIC int32 800 _phy_82328_config_update(int32 unit, soc_port_t port) 801 { 802 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 803 804 /* Change polarity got from config */ 805 return _phy_82328_polarity_flip(unit, port, POL_TX_CFG(pc), POL_RX_CFG(pc)); 806 } 807 808 #ifdef BCM_WARM_BOOT_SUPPORT 809 810 STATIC int32 811 _phy_82328_intf_speed_from_reg(uint16 mode, int32 *speed) 812 { 813 uint16 speed_reg = mode & (MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_1G_MASK | 814 MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_10G_MASK | 815 MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_40G_MASK | 816 MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_100G_MASK ); 817 *speed = 0; 818 switch (speed_reg) { 819 820 case PHY82328_GP_REG_1_SPD_42G: 821 *speed = PHY82328_SPD_42G; 822 break; 823 824 case PHY82328_GP_REG_1_SPD_40G: 825 *speed = PHY82328_SPD_40G; 826 break; 827 828 case PHY82328_GP_REG_1_SPD_10G: 829 *speed = PHY82328_SPD_10G; 830 break; 831 case PHY82328_GP_REG_1_SPD_1G: 832 /********* 100, 10 not recoverable from PHY ********/ 833 *speed = PHY82328_SPD_1G; 834 break; 835 836 default: 837 /* hardware has unexpected value */ 838 return SOC_E_FAIL; 839 } 840 841 return SOC_E_NONE; 842 } 843 844 STATIC int32 845 _phy_82328_intf_type_from_reg(uint16 mode, phy82328_intf_side_t side, int32 speed, int32 an, 846 soc_port_if_t *intf_type) 847 { 848 uint16 intf_reg = mode & ((side == PHY82328_INTF_SIDE_LINE) ? 0x5300 : 0xac00); 849 850 if (side == PHY82328_INTF_SIDE_LINE) { 851 if (intf_reg == 0) { 852 if (speed == PHY82328_SPD_40G || speed == PHY82328_SPD_42G) { 853 *intf_type = SOC_PORT_IF_SR4; 854 } else if (speed == PHY82328_SPD_10G) { 855 *intf_type = SOC_PORT_IF_SR; 856 } else if (speed == PHY82328_SPD_1G) { 857 if (an) { 858 *intf_type = SOC_PORT_IF_GMII; 859 } else { 860 *intf_type = SOC_PORT_IF_SGMII; 861 } 862 } else if (speed == 100 || speed == 10) { 863 *intf_type = SOC_PORT_IF_SGMII; 864 } 865 else { 866 return SOC_E_FAIL; 867 } 868 } else if (intf_reg == 0x4200) { 869 if (speed == PHY82328_SPD_40G || speed == PHY82328_SPD_42G) { 870 *intf_type = SOC_PORT_IF_XLAUI; 871 } else if (speed == PHY82328_SPD_10G) { 872 *intf_type = SOC_PORT_IF_SFI; 873 } else { 874 return SOC_E_FAIL; 875 } 876 } else if (intf_reg == 0x4000) { 877 if (speed == PHY82328_SPD_40G || speed == PHY82328_SPD_42G) { 878 *intf_type = SOC_PORT_IF_LR4; 879 } else if (speed == PHY82328_SPD_10G) { 880 *intf_type = SOC_PORT_IF_LR; 881 } else { 882 return SOC_E_FAIL; 883 } 884 } else if (intf_reg == 0x200 || intf_reg == 0x1200) { 885 if (speed == PHY82328_SPD_40G || speed == PHY82328_SPD_42G) { 886 *intf_type = SOC_PORT_IF_CR4; 887 } else if (speed == PHY82328_SPD_10G) { 888 *intf_type = SOC_PORT_IF_CR; 889 } 890 else { 891 return SOC_E_FAIL; 892 } 893 } else if (intf_reg == 0x100) { 894 if (speed == PHY82328_SPD_40G || speed == PHY82328_SPD_42G) { 895 *intf_type = SOC_PORT_IF_KR4; 896 } else if (speed == PHY82328_SPD_10G) { 897 *intf_type = SOC_PORT_IF_KR; 898 } else if (speed == PHY82328_SPD_1G || speed == 100 || speed == 10) { 899 *intf_type = SOC_PORT_IF_KX; 900 } 901 else { 902 return SOC_E_FAIL; 903 } 904 } else if (intf_reg == 0x5000) { 905 if (speed == PHY82328_SPD_10G) { 906 *intf_type = SOC_PORT_IF_ZR; 907 } else { 908 return SOC_E_FAIL; 909 } 910 } else { 911 return SOC_E_FAIL; 912 } /* if (intf_reg) */ 913 } else { 914 if (intf_reg == 0) { 915 if (speed == PHY82328_SPD_40G || speed == PHY82328_SPD_42G) { 916 *intf_type = SOC_PORT_IF_SR4; 917 } else if (speed == PHY82328_SPD_10G) { 918 *intf_type = SOC_PORT_IF_SR; 919 } else if (speed == PHY82328_SPD_1G) { 920 if (an) { 921 *intf_type = SOC_PORT_IF_GMII; 922 } else { 923 *intf_type = SOC_PORT_IF_SGMII; 924 } 925 } else if (speed == 100 || speed == 10) { 926 *intf_type = SOC_PORT_IF_SGMII; 927 } 928 else { 929 return SOC_E_FAIL; 930 } 931 } else if (intf_reg == 0x8800) { 932 if (speed == PHY82328_SPD_40G || speed == PHY82328_SPD_42G) { 933 *intf_type = SOC_PORT_IF_XLAUI; 934 } else if (speed == PHY82328_SPD_10G) { 935 *intf_type = SOC_PORT_IF_XFI; 936 } 937 else { 938 return SOC_E_FAIL; 939 } 940 } else if (intf_reg == 0x800 || intf_reg == 0x2800) { 941 if (speed == PHY82328_SPD_40G || speed == PHY82328_SPD_42G) { 942 *intf_type = SOC_PORT_IF_CR4; 943 } else if (speed == PHY82328_SPD_10G) { 944 *intf_type = SOC_PORT_IF_CR; 945 } 946 else { 947 return SOC_E_FAIL; 948 } 949 } else if (intf_reg == 0x400) { 950 if (speed == PHY82328_SPD_40G || speed == PHY82328_SPD_42G) { 951 *intf_type = SOC_PORT_IF_KR4; 952 } else if (speed == PHY82328_SPD_10G) { 953 *intf_type = SOC_PORT_IF_KR; 954 } else if (speed == PHY82328_SPD_1G || speed == 10 || speed == 100) { 955 *intf_type = SOC_PORT_IF_KX; 956 } 957 else { 958 return SOC_E_FAIL; 959 } 960 } else { 961 return SOC_E_FAIL; 962 } 963 } 964 return SOC_E_NONE; 965 } 966 967 STATIC int32 968 _phy_82328_reinit_line_intf(int32 unit, soc_port_t port, int32 speed, int32 an, uint16 mode) 969 { 970 phy_ctrl_t *pc; 971 phy82328_intf_cfg_t *line_intf; 972 973 pc = EXT_PHY_SW_STATE(unit, port); 974 line_intf = &(LINE_INTF(pc)); 975 976 line_intf->speed = speed; 977 SOC_IF_ERROR_RETURN(_phy_82328_intf_type_from_reg(mode, PHY82328_INTF_SIDE_LINE, speed, an, &(line_intf->type))); 978 979 return SOC_E_NONE; 980 } 981 982 STATIC int32 983 _phy_82328_reinit_system_intf(int32 unit, soc_port_t port, int32 speed, int32 an, uint16 mode) 984 { 985 phy_ctrl_t *pc; 986 phy82328_intf_cfg_t *system_intf; 987 988 pc = EXT_PHY_SW_STATE(unit, port); 989 system_intf = &(SYS_INTF(pc)); 990 991 system_intf->speed = speed; 992 SOC_IF_ERROR_RETURN(_phy_82328_intf_type_from_reg(mode, PHY82328_INTF_SIDE_SYS, speed, an, &(system_intf->type))); 993 994 return SOC_E_NONE; 995 } 996 997 STATIC int32 998 _phy_82328_reinit_cur_datapath(int32 unit, soc_port_t port, uint16 mode) 999 { 1000 uint16 datapath_reg; 1001 phy_ctrl_t *pc; 1002 1003 pc = EXT_PHY_SW_STATE(unit, port); 1004 1005 datapath_reg = mode & (MGT_TOP_PMD_USR_GP_REGISTER_1_ENABLE_ULTRA_LOW_LATENCY_DATAPATH_MASK | 1006 MGT_TOP_PMD_USR_GP_REGISTER_1_ULL_DATAPATH_LATENCY_MASK); 1007 1008 if (datapath_reg == 0) { 1009 CUR_DATAPATH(pc) = PHY82328_DATAPATH_20; 1010 } else if (datapath_reg == PHY82328_4BIT_DP_DEPTH1) { 1011 CUR_DATAPATH(pc) = PHY82328_DATAPATH_4_DEPTH_1; 1012 } else if ( datapath_reg == PHY82328_4BIT_DP_DEPTH2) { 1013 CUR_DATAPATH(pc) = PHY82328_DATAPATH_4_DEPTH_2; 1014 } else { 1015 return SOC_E_FAIL; 1016 } 1017 return SOC_E_NONE; 1018 } 1019 1020 STATIC int32 1021 _phy_82328_reinit_from_mode(int32 unit, soc_port_t port) 1022 { 1023 uint16 mode_reg = 0, side_reg, an_reg; 1024 int32 speed = 0, an =0, an_done = 0; 1025 phy_ctrl_t *pc, *int_pc; 1026 1027 pc = EXT_PHY_SW_STATE(unit, port); 1028 int_pc = INT_PHY_SW_STATE(unit, port); 1029 1030 if (int_pc == NULL) { 1031 return SOC_E_UNAVAIL; 1032 } 1033 /* 1034 * Make sure line side registers are selected 1035 * if not, have to bail out since the system is in a bad state 1036 */ 1037 SOC_IF_ERROR_RETURN( 1038 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_XPMD_REGS_SEL, &side_reg)); 1039 if (side_reg != 0) { 1040 return SOC_E_UNAVAIL; 1041 } 1042 1043 /* Read the current mode */ 1044 SOC_IF_ERROR_RETURN( 1045 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REGISTER_3, &mode_reg)); 1046 1047 /* Get speed */ 1048 SOC_IF_ERROR_RETURN(_phy_82328_intf_speed_from_reg(mode_reg, &speed)); 1049 1050 /* Get an setting */ 1051 if (speed < PHY82328_SPD_10G ) { 1052 SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_GET(int_pc->pd, unit, port, &an, &an_done)); 1053 SOC_IF_ERROR_RETURN(PHY_SPEED_GET(int_pc->pd, unit, port, &speed)); 1054 } else { 1055 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_AN_REG(unit, pc, 1056 PHY82328_AN_CTRL_REG, &an_reg)); 1057 an = ((an_reg & PHY82328_AN_ENABLE_MSK) == PHY82328_AN_ENABLE_MSK); 1058 } 1059 1060 AN_EN(pc) = an; 1061 #if 1 1062 SOC_IF_ERROR_RETURN( 1063 _phy_82328_reinit_line_intf(unit, port, speed, an, mode_reg)); 1064 SOC_IF_ERROR_RETURN( 1065 _phy_82328_reinit_system_intf(unit, port, speed, an, mode_reg)); 1066 #endif 1067 SOC_IF_ERROR_RETURN( 1068 _phy_82328_reinit_cur_datapath(unit, port, mode_reg)); 1069 1070 return SOC_E_NONE; 1071 } 1072 1073 STATIC int32 1074 _phy_82328_reinit_fw_rx_los(int32 unit, soc_port_t port) 1075 { 1076 uint16 data16 = 0; 1077 phy_ctrl_t *pc; 1078 1079 pc = EXT_PHY_SW_STATE(unit, port); 1080 1081 SOC_IF_ERROR_RETURN( 1082 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, SIGDET_SIGDET_CTRL_1, &data16)); 1083 1084 FW_RX_LOS(pc) = (data16 & SIGDET_SIGDET_CTRL_1_SIGNAL_DETECT_FRC_MASK) >> 1085 SIGDET_SIGDET_CTRL_1_SIGNAL_DETECT_FRC_SHIFT; 1086 1087 return SOC_E_NONE; 1088 } 1089 1090 STATIC int32 1091 _phy_82328_reinit(int32 unit, soc_port_t port) 1092 { 1093 SOC_IF_ERROR_RETURN( 1094 _phy_82328_reinit_from_mode(unit , port)); 1095 1096 /* Reinit fw_rx_los */ 1097 SOC_IF_ERROR_RETURN( 1098 _phy_82328_reinit_fw_rx_los(unit, port)); 1099 1100 return SOC_E_NONE; 1101 } 1102 1103 #endif /* BCM_WARM_BOOT_SUPPORT */ 1104 1105 STATIC int32 1106 _phy_82328_init_pass2(int32 unit, soc_port_t port) 1107 { 1108 phy_ctrl_t *pc; 1109 phy82328_intf_cfg_t *line_intf, *sys_intf; 1110 phy82328_micro_ctrl_t *micro_ctrl; 1111 uint16 if_sys_idx = 0; 1112 uint16 chan_data = 0, chan_mask = 0; 1113 1114 LOG_INFO(BSL_LS_SOC_PHY, 1115 (BSL_META_U(unit, 1116 "PHY82328 init pass2: u=%d p=%d\n"), unit, port)); 1117 pc = EXT_PHY_SW_STATE(unit, port); 1118 /* 1119 * - interfaces are KR4/KR/KX/XAUI/XFI/SR/LR/CR/SR4/LR4/CR4 1120 * - Gallardo is capable of being configured symmetrically and can support all 1121 * interfaces on both sides 1122 * - system side interfaces cannot be changed dynamically 1123 * - configured in Gallardo via config variables 1124 * - line side mode can be changed dynamically 1125 * - configured specifically with interface set and/or by matching speed 1126 * - automatically when module autodetect is enabled 1127 * 1128 * port mode system side line side 1129 * ---------------- ------------------------ -------------------------------- 1130 * 40G(singleport) dflt:XLAUI or configvar dflt:XLAUI or user set if/speed 1131 * 1G/10G(quadport) dflt:XFI or configvar dflt:SFI or user set if/speed 1132 */ 1133 1134 line_intf = &(LINE_INTF(pc)); 1135 sys_intf = &(SYS_INTF(pc)); 1136 micro_ctrl = &(MICRO_CTRL(pc)); 1137 1138 sal_memset(line_intf, 0, sizeof(phy82328_intf_cfg_t)); 1139 sal_memset(sys_intf, 0, sizeof(phy82328_intf_cfg_t)); 1140 sal_memset(micro_ctrl, 0, sizeof(phy82328_micro_ctrl_t)); 1141 1142 AN_EN(pc) = 0; 1143 SYNC_INIT(pc) = 1; 1144 FW_RX_LOS(pc) = 0; 1145 LOGICAL_LANE0(pc) = 0; 1146 micro_ctrl->enable = 1; 1147 micro_ctrl->count = 0; 1148 1149 SYS_FORCED_CL72(pc) = soc_property_port_get(unit, port, spn_PORT_INIT_CL72, 0); 1150 pc->flags |= PHYCTRL_INIT_DONE; 1151 /* Get configured system interface */ 1152 if_sys_idx = soc_property_port_get(unit, port, spn_PHY_SYS_INTERFACE, 0); 1153 if (if_sys_idx >= (sizeof(phy82328_sys_to_port_if) / sizeof(soc_port_if_t))) { 1154 LOG_ERROR(BSL_LS_SOC_PHY, 1155 (BSL_META_U(unit, 1156 "PHY82328 invalid system side interface: u=%d p=%d intf=%d\n" 1157 "Using default interface\n"), 1158 unit, port, if_sys_idx)); 1159 if_sys_idx = 0; 1160 } 1161 sys_intf->type = phy82328_sys_to_port_if[if_sys_idx]; 1162 if (PHY82328_SINGLE_PORT_MODE(pc)) { 1163 line_intf->speed = PHY82328_SPD_40G; 1164 } 1165 else { 1166 line_intf->speed = PHY82328_SPD_10G; 1167 } 1168 if (sys_intf->type == 0) { 1169 /* use defaults based on current line side */ 1170 sys_intf->speed = line_intf->speed; 1171 if ( line_intf->speed == PHY82328_SPD_40G) { 1172 line_intf->type = SOC_PORT_IF_SR4; 1173 sys_intf->type = SOC_PORT_IF_XLAUI; 1174 } 1175 else { 1176 line_intf->type = SOC_PORT_IF_SR; 1177 sys_intf->type = SOC_PORT_IF_XFI; 1178 } 1179 LOG_INFO(BSL_LS_SOC_PHY, 1180 (BSL_META_U(unit, 1181 "default sys and line intf are used\n"))); 1182 } else { 1183 SOC_IF_ERROR_RETURN(_phy_82328_intf_line_sys_params_get(unit, port)); 1184 LOG_CLI((BSL_META_U(unit, 1185 "After updating intf based on sys config\n"))); 1186 LOG_CLI((BSL_META_U(unit, 1187 "SYS Intf:%s speed:%d\n"), 1188 phy82328_intf_names[sys_intf->type],sys_intf->speed)); 1189 LOG_CLI((BSL_META_U(unit, 1190 "Line intf:%s speed:%d\n"), 1191 phy82328_intf_names[line_intf->type],line_intf->speed)); 1192 } 1193 CFG_SYS_INTF(pc) = sys_intf->type; 1194 CFG_DATAPATH(pc) = soc_property_port_get(unit, port, "82328_DATAPATH", PHY82328_DATAPATH_20); 1195 CUR_DATAPATH(pc) = CFG_DATAPATH(pc); 1196 1197 /* Polarity configuration is applied every time interface is configured */ 1198 POL_TX_CFG(pc) = soc_property_port_get(unit, port, spn_PHY_TX_POLARITY_FLIP, PHY82328_POL_DND); 1199 POL_RX_CFG(pc) = soc_property_port_get(unit, port, spn_PHY_RX_POLARITY_FLIP, PHY82328_POL_DND); 1200 1201 PHY_82328_MICRO_PAUSE(unit, port, "polarity config in Init"); 1202 1203 /* Push configuration to the device */ 1204 SOC_IF_ERROR_RETURN(_phy_82328_config_update(unit, port)); 1205 1206 PHY_82328_MICRO_RESUME(unit, port); 1207 /* Manually power down channel*/ 1208 chan_data = (1 << MGT_TOP_PMD_USR_OPTICAL_CONFIGURATION_MAN_TXON_EN_SHIFT) | 1209 (1 << MGT_TOP_PMD_USR_OPTICAL_CONFIGURATION_TXOFFT_SHIFT); 1210 chan_mask = MGT_TOP_PMD_USR_OPTICAL_CONFIGURATION_MAN_TXON_EN_MASK | 1211 MGT_TOP_PMD_USR_OPTICAL_CONFIGURATION_TXOFFT_MASK; 1212 1213 SOC_IF_ERROR_RETURN( 1214 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_OPTICAL_CONFIGURATION, 1215 chan_data, chan_mask)); 1216 #ifdef BCM_WARM_BOOT_SUPPORT 1217 if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)){ 1218 /* Do nothing */ 1219 } else 1220 #endif 1221 { 1222 /* Initialize system and line side interfaces */ 1223 SOC_IF_ERROR_RETURN(_phy_82328_intf_line_sys_init(unit, port)); 1224 } 1225 1226 #ifdef BCM_WARM_BOOT_SUPPORT 1227 if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)){ 1228 return _phy_82328_reinit(unit, port); 1229 } 1230 #endif 1231 if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) { 1232 /* indicate third pass of init is needed */ 1233 PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS3); 1234 } 1235 return SOC_E_NONE; 1236 } 1237 1238 STATIC int 1239 _phy_82328_init_pass3(int unit, soc_port_t port) 1240 { 1241 int rv; 1242 phy_ctrl_t *pc, *int_pc; 1243 1244 LOG_INFO(BSL_LS_SOC_PHY, 1245 (BSL_META_U(unit, 1246 "PHY82328 init pass3: u=%d p=%d\n"), unit, port)); 1247 pc = EXT_PHY_SW_STATE(unit, port); 1248 int_pc = INT_PHY_SW_STATE(unit, port); 1249 1250 /* Complete what we started from PASS2 in PASS3 */ 1251 if (INT_PHY_RE_EN(pc)) { 1252 /* wait for timer to expire */ 1253 while (!soc_timeout_check(&SYNC_TO(pc))) { 1254 sal_usleep(100); 1255 } 1256 1257 /* Turn internal PHY back on now that the mode has been configured */ 1258 SOC_IF_ERROR_RETURN(PHY_ENABLE_SET(int_pc->pd, unit, port, 1)); 1259 INT_PHY_RE_EN(pc) = 0; 1260 } 1261 /* Logical lane0 used for auto-negotiation in 40G CR4 */ 1262 if (PHY82328_SINGLE_PORT_MODE(pc)) { 1263 uint16 logical_lane0; 1264 1265 logical_lane0 = soc_property_port_get(unit, port, spn_PHY_LANE0_L2P_MAP, 0); 1266 if (logical_lane0 > PHY82328_NUM_LANES) { 1267 LOG_ERROR(BSL_LS_SOC_PHY, 1268 (BSL_META_U(unit, 1269 "PHY82328 bad auto-negotiation lane %d: u=%d p=%d" 1270 " lane must be 0..3\n"), (int)logical_lane0, unit, port)); 1271 } else { 1272 SOC_IF_ERROR_RETURN( 1273 MODIFY_PHY82328_MMF_PMA_PMD_REG( 1274 unit, pc, MGT_TOP_SINGLE_PMD_CTRL, 1275 logical_lane0 << MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_PHY_CH_TO_ACCESS_IN_SINGLE_PMD_SHIFT, 1276 MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_PHY_CH_TO_ACCESS_IN_SINGLE_PMD_MASK)); 1277 LOGICAL_LANE0(pc) = logical_lane0; 1278 } 1279 } 1280 1281 /* If configured, enable module auto detection */ 1282 MOD_AUTO_DETECT(pc) = soc_property_port_get(unit, port, spn_PHY_MOD_AUTO_DETECT, 0); 1283 if (MOD_AUTO_DETECT(pc)) { 1284 uint16 data, mask; 1285 1286 LOG_INFO(BSL_LS_SOC_PHY, 1287 (BSL_META_U(unit, 1288 "PHY82328 module auto detect enabled: u=%d p=%d\n"), 1289 unit, port)); 1290 1291 /* Enables both SFP and QSFP module detect */ 1292 data = (MGT_TOP_CMN_CTLR_GP_REG_0_ENABLE_QSFP_MOD_DETECT_MASK | 1293 MGT_TOP_CMN_CTLR_GP_REG_0_ENABLE_SFP_MOD_DETECT_MASK); 1294 mask = (MGT_TOP_CMN_CTLR_GP_REG_0_ENABLE_QSFP_MOD_DETECT_MASK | 1295 MGT_TOP_CMN_CTLR_GP_REG_0_ENABLE_SFP_MOD_DETECT_MASK); 1296 1297 rv = MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REG_0, data, mask); 1298 if (SOC_FAILURE(rv)) { 1299 MOD_AUTO_DETECT(pc) = 0; 1300 LOG_ERROR(BSL_LS_SOC_PHY, 1301 (BSL_META_U(unit, 1302 "PHY82328 setting module auto detect failed: u=%d p%d\n"), 1303 unit, port)); 1304 } 1305 } 1306 #ifdef BCM_WARM_BOOT_SUPPORT 1307 if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)){ 1308 return _phy_82328_reinit(unit, port); 1309 } 1310 #endif 1311 1312 /* Cold boot code only below this */ 1313 return SOC_E_NONE; 1314 } 1315 1316 /* 1317 * Check if the core has been initialized. This is done by 1318 * looking at all ports which belong to the same core and see 1319 * if any one of them have completed initialization. 1320 * The primary port is used to determine whether the port is 1321 * on the same core as all ports in a core share the primary port. 1322 */ 1323 STATIC int32 1324 _phy_82328_core_init_done(int32 unit, struct phy_driver_s *pd, int32 primary_port) 1325 { 1326 int32 rv; 1327 soc_port_t port; 1328 phy_ctrl_t *pc; 1329 uint32 core_primary_port; 1330 1331 PBMP_ALL_ITER(unit, port) { 1332 pc = EXT_PHY_SW_STATE(unit, port); 1333 if (pc == NULL) { 1334 continue; 1335 } 1336 /* Make sure this port has a 82328 driver */ 1337 if (pc->pd != pd) { 1338 continue; 1339 } 1340 rv = phy_82328_control_get(unit, port, SOC_PHY_CONTROL_PORT_PRIMARY, 1341 &core_primary_port); 1342 if (rv != SOC_E_NONE) { 1343 continue; 1344 } 1345 if ((primary_port == core_primary_port) && (pc->flags & PHYCTRL_INIT_DONE)) { 1346 return TRUE; 1347 } 1348 } 1349 return FALSE; 1350 } 1351 1352 1353 STATIC int32 1354 _phy_82328_init_pass1(int32 unit, soc_port_t port) 1355 { 1356 phy_ctrl_t *pc; 1357 int32 offset; 1358 soc_port_t primary_port; 1359 uint16 chip_rev; 1360 1361 pc = EXT_PHY_SW_STATE(unit, port); 1362 1363 LOG_INFO(BSL_LS_SOC_PHY, 1364 (BSL_META_U(unit, 1365 "PHY82328 init pass1: u=%d p=%d\n"), unit, port)); 1366 1367 SOC_IF_ERROR_RETURN( 1368 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 1369 MGT_TOP_CHIP_REV_REGISTER, 1370 &chip_rev)); 1371 DEVREV(pc) = chip_rev; 1372 /* Set the primary port & offset */ 1373 if (soc_phy_primary_and_offset_get(unit, port, &primary_port, &offset) != SOC_E_NONE) { 1374 /* 1375 * Derive primary and offset 1376 * There is an assumption lane 0 on first core on the the MDIO 1377 * bus is a primary port 1378 */ 1379 if (PHY82328_SINGLE_PORT_MODE(pc)) { 1380 primary_port = port; 1381 offset = 0; 1382 } else { 1383 /*primary_port = port - (pc->phy_id & 0x3);*/ 1384 if ((port-1) == 0) { 1385 primary_port = (((port)/4) * 4) + 1; 1386 } else { 1387 primary_port = (((port -1)/4) * 4) + 1; 1388 } 1389 offset = pc->phy_id & 0x3; 1390 } 1391 } 1392 /* set the default values that are valid for many boards */ 1393 SOC_IF_ERROR_RETURN(phy_82328_control_set(unit, port, SOC_PHY_CONTROL_PORT_PRIMARY, 1394 primary_port)); 1395 1396 SOC_IF_ERROR_RETURN(phy_82328_control_set(unit, port,SOC_PHY_CONTROL_PORT_OFFSET, 1397 offset)); 1398 1399 /* 1400 * Since there is a single micro and therefore a single copy of the firmware 1401 * shared among the 4 channels in a core, do not download firmware if in quad 1402 * channel and the other channels are active. 1403 */ 1404 if (PHY82328_SINGLE_PORT_MODE(pc) || 1405 (!PHY82328_SINGLE_PORT_MODE(pc) && 1406 (!_phy_82328_core_init_done(unit, pc->pd, primary_port)))) { 1407 uint16 sts_reg = 0; 1408 SOC_IF_ERROR_RETURN 1409 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 1410 MGT_TOP_SPA_CONTROL_STATUS_REGISTER, &sts_reg)); 1411 1412 if ((sts_reg & (1 << 13)) && 1413 !(soc_property_port_get(unit, port, 1414 spn_PHY_FORCE_FIRMWARE_LOAD, FALSE))) { 1415 pc->flags &= (~PHYCTRL_MDIO_BCST); 1416 } else { 1417 LOG_INFO(BSL_LS_SOC_PHY, 1418 (BSL_META_U(unit, 1419 "PHY82328 Bcast Enabled for Port:%d"), port)); 1420 pc->flags |= PHYCTRL_MDIO_BCST; 1421 } 1422 } 1423 1424 /* indicate second pass of init is needed */ 1425 PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS2); 1426 1427 return SOC_E_NONE; 1428 } 1429 1430 STATIC int32 1431 _phy_82328_chip_id_get(int32 unit, soc_port_t port, phy_ctrl_t *pc, uint32 *chip_id) 1432 { 1433 int32 rv = SOC_E_NONE; 1434 1435 uint16 chip_id_lsb = 0, chip_id_msb = 0, chip_id_misc = 0; 1436 1437 *chip_id = 0; 1438 1439 SOC_IF_ERROR_RETURN( 1440 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_CHIP_ID0_REGISTER, &chip_id_lsb)); 1441 SOC_IF_ERROR_RETURN( 1442 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_CHIP_ID1_REGISTER, &chip_id_msb)); 1443 SOC_IF_ERROR_RETURN( 1444 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_OTP_MISC_SIG4_REGISTER, &chip_id_misc)); 1445 1446 if (chip_id_msb == 0x8) { 1447 if (chip_id_lsb == 0x2328) { 1448 if (chip_id_misc & (1U << 12)) { 1449 *chip_id = PHY82328_ID_82328F; 1450 } else { 1451 *chip_id = PHY82328_ID_82328; 1452 } 1453 } else if (chip_id_lsb == 0x2322) { 1454 *chip_id = PHY82328_ID_82322; 1455 } else if (chip_id_lsb == 0x232F) { 1456 *chip_id = PHY82328_ID_82328F; 1457 } else { 1458 LOG_ERROR(BSL_LS_SOC_PHY, 1459 (BSL_META_U(unit, 1460 "PHY82328 bad chip id: u=%d p=%d chipid %x%x\n"), 1461 unit, port, chip_id_msb, chip_id_lsb)); 1462 rv = SOC_E_BADID; 1463 } 1464 } 1465 return rv; 1466 } 1467 1468 STATIC int32 1469 _phy_82328_config_devid(int32 unit,soc_port_t port, phy_ctrl_t *pc, uint32 *devid) 1470 { 1471 if (soc_property_port_get(unit, port, "phy_82328", FALSE)) { 1472 return *devid = PHY82328_ID_82328; 1473 } else if(soc_property_port_get(unit, port, "phy_82328f", FALSE)) { 1474 return *devid = PHY82328_ID_82328F; 1475 } else if(soc_property_port_get(unit, port, "phy_82322", FALSE)) { 1476 return *devid = PHY82328_ID_82322; 1477 } 1478 1479 return _phy_82328_chip_id_get(unit, port, pc, devid); 1480 } 1481 1482 /* Function: 1483 * phy_82328_init 1484 * Purpose: 1485 * Initialize 82328 phys 1486 * Parameters: 1487 * unit - StrataSwitch unit #. 1488 * port - StrataSwitch port #. 1489 * Returns: 1490 * SOC_E_NONE 1491 */ 1492 1493 STATIC 1494 int32 phy_82328_init(int32 unit, soc_port_t port) 1495 { 1496 int32 ix; 1497 uint32 devid; 1498 phy_ctrl_t *pc; 1499 1500 pc = EXT_PHY_SW_STATE(unit, port); 1501 1502 LOG_INFO(BSL_LS_SOC_PHY, 1503 (BSL_META_U(unit, 1504 "PHY82328 init: u=%d p=%d state=%d\n"), 1505 unit, port,PHYCTRL_INIT_STATE(pc))); 1506 SOC_IF_ERROR_RETURN( 1507 phy82328_intf_side_reg_select (unit, port, PHY82328_INTF_SIDE_LINE)); 1508 1509 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) || 1510 (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) { 1511 1512 /* Read the chip id to identify the device */ 1513 SOC_IF_ERROR_RETURN(_phy_82328_config_devid(unit, port, pc, &devid)); 1514 1515 /* Save it in the device description structure for future use */ 1516 DEVID(pc) = devid; 1517 1518 /* initialize default p2l map */ 1519 for (ix = 0; ix < PHY82328_NUM_LANES; ix++) { 1520 P2L_MAP(pc,ix) = ix; 1521 } 1522 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER | PHY_FLAGS_C45 | PHY_FLAGS_REPEATER); 1523 SOC_IF_ERROR_RETURN(_phy_82328_init_pass1(unit, port)); 1524 1525 if (PHYCTRL_INIT_STATE(pc) != PHYCTRL_INIT_STATE_DEFAULT) { 1526 return SOC_E_NONE; 1527 } 1528 } 1529 1530 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) || 1531 (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) { 1532 SOC_IF_ERROR_RETURN (_phy_82328_init_pass2(unit, port)); 1533 if (PHYCTRL_INIT_STATE(pc) != PHYCTRL_INIT_STATE_DEFAULT) { 1534 return SOC_E_NONE; 1535 } 1536 } 1537 1538 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS3) || 1539 (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) { 1540 1541 SOC_IF_ERROR_RETURN( _phy_82328_init_pass3(unit, port)); 1542 1543 LOG_INFO(BSL_LS_SOC_PHY, 1544 (BSL_META_U(unit, 1545 "PHY82328 init pass3 completed: u=%d p=%d\n"), unit, port)); 1546 PHYCTRL_INIT_STATE_SET(pc, PHYCTRL_INIT_STATE_DEFAULT); 1547 return SOC_E_NONE; 1548 } 1549 1550 return SOC_E_NONE; 1551 } 1552 1553 /* Return contents of ANARXSTATUS */ 1554 STATIC int32 1555 _phy_82328_intf_link_get(int32 unit, soc_port_t port, int32 *link) 1556 { 1557 int32 lane=0, max_lane=0; 1558 uint16 data16=0; 1559 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 1560 1561 if (PHY82328_SINGLE_PORT_MODE(pc)) { 1562 max_lane = PHY82328_NUM_LANES; 1563 } 1564 else { 1565 max_lane = 1; 1566 } 1567 for (lane = 0; lane < max_lane; lane++) { 1568 if (PHY82328_SINGLE_PORT_MODE(pc)) { 1569 /* Select the lane on the line side */ 1570 SOC_IF_ERROR_RETURN( 1571 _phy_82328_channel_select(unit, port, PHY82328_INTF_SIDE_LINE, lane)); 1572 } 1573 if (AN_EN(pc) == 1) { 1574 /*anaRxStatusSel 1.C0B1.[2:0] 0*/ 1575 SOC_IF_ERROR_RETURN( 1576 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, PHY82328_AN_STS_REG, 1577 &data16)); 1578 if (data16 & PHY82328_AN_STS_LINK_STS_MSK) { 1579 *link &=1; 1580 } else { 1581 *link &=0; 1582 } 1583 } else { 1584 /*anaRxStatusSel 1.C0B1.[2:0] 0*/ 1585 SOC_IF_ERROR_RETURN( 1586 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, RX_ANARXCONTROL, 1587 0x0, QSFI_RX_ANARXSTATUS_SM_SEL_MASK)); 1588 /*anaRxStatusSel 1.C0B0.12 1*/ 1589 SOC_IF_ERROR_RETURN( 1590 READ_PHY82328_MMF_PMA_PMD_REG (unit, pc, RX_ANARXSTATUS, &data16)); 1591 1592 /* Check if rxSeq Done in any lane */ 1593 if ((data16 & QSFI_RX_ANARXSTATUS_PMD_RX_PMD_LOCK_MASK) == 1594 QSFI_RX_ANARXSTATUS_PMD_RX_PMD_LOCK_MASK) { 1595 *link &= 1; 1596 } else { 1597 *link = 0; 1598 } 1599 LOG_VERBOSE(BSL_LS_SOC_PHY, 1600 (BSL_META_U(unit, 1601 "PhyID:%x link:%d"), 1602 pc->phy_id,*link)); 1603 } 1604 #if 0 1605 if (LINE_INTF(pc).speed == 10000) { 1606 LOG_CLI((BSL_META_U(unit, 1607 "Speed 10G: link:%d\n"), *link)); 1608 break; 1609 } 1610 #endif 1611 } 1612 LOG_VERBOSE(BSL_LS_SOC_PHY, 1613 (BSL_META_U(unit, 1614 "-->After MOD PhyID:%x\n"), 1615 pc->phy_id)); 1616 1617 /* Restore to default single port register access */ 1618 if (PHY82328_SINGLE_PORT_MODE(pc)) { 1619 SOC_IF_ERROR_RETURN 1620 (_phy_82328_channel_select(unit, port, PHY82328_INTF_SIDE_LINE, 1621 PHY82328_ALL_LANES)); 1622 } 1623 return SOC_E_NONE; 1624 } 1625 1626 STATIC int 1627 _phy_82328_mod_auto_detect_speed_check(int unit, soc_port_t port, uint16 csr) 1628 { 1629 uint16 csr_speed; 1630 phy_ctrl_t *pc; 1631 phy82328_intf_cfg_t *line_intf; 1632 static int speed_tbl[] = { 0, 1000, 10000, 0, 40000, 0, 0 ,0, 10000 }; 1633 1634 pc = EXT_PHY_SW_STATE(unit, port); 1635 line_intf = &(LINE_INTF(pc)); 1636 1637 csr_speed = csr & (MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_100G_MASK | 1638 MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_40G_MASK | 1639 MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_10G_MASK | 1640 MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_1G_MASK); 1641 if (line_intf->speed != speed_tbl[csr_speed]) { 1642 LOG_ERROR(BSL_LS_SOC_PHY, 1643 (BSL_META_U(unit, 1644 "82328 module auto detection unexpected: u=%d p=%d speed=0x%x\n"), 1645 unit, port, speed_tbl[csr_speed])); 1646 } 1647 return (line_intf->speed == speed_tbl[csr_speed]); 1648 } 1649 1650 STATIC int 1651 _phy_82328_mod_auto_detect_intf_process(int unit, soc_port_t port, uint16 csr) 1652 { 1653 int copper_mod = 0; 1654 int lr_mod = 0; 1655 phy_ctrl_t *pc; 1656 phy82328_intf_cfg_t *line_intf; 1657 int intf_update = 1; 1658 1659 pc = EXT_PHY_SW_STATE(unit, port); 1660 line_intf = &(LINE_INTF(pc)); 1661 1662 copper_mod = (csr & MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_CU_TYPE_MASK) == 1663 MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_CU_TYPE_MASK; 1664 1665 lr_mod = (csr & MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_LR_MODE_MASK) == 1666 MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_LR_MODE_MASK; 1667 1668 /* Change interface if going from optical to copper */ 1669 if (copper_mod) { 1670 switch (line_intf->type) { 1671 case SOC_PORT_IF_SR: 1672 case SOC_PORT_IF_SFI: 1673 case SOC_PORT_IF_XFI: 1674 line_intf->type = SOC_PORT_IF_CR; 1675 break; 1676 case SOC_PORT_IF_SR4: 1677 case SOC_PORT_IF_XLAUI: 1678 line_intf->type = SOC_PORT_IF_CR4; 1679 break; 1680 default: 1681 /* No interface change if not currently an optical interface */ 1682 intf_update = 0; 1683 break; 1684 } 1685 } else { 1686 /* Change interface if going from optical SR to LR */ 1687 if (lr_mod) { 1688 switch (line_intf->type) { 1689 case SOC_PORT_IF_SR: 1690 case SOC_PORT_IF_SFI: 1691 case SOC_PORT_IF_XFI: 1692 line_intf->type = SOC_PORT_IF_LR; 1693 break; 1694 case SOC_PORT_IF_SR4: 1695 case SOC_PORT_IF_XLAUI: 1696 line_intf->type = SOC_PORT_IF_LR4; 1697 break; 1698 default: 1699 /* No interface change */ 1700 intf_update = 0; 1701 break; 1702 } 1703 } 1704 /* Change interface if going from copper to optical */ 1705 switch (line_intf->type) { 1706 case SOC_PORT_IF_CR: 1707 line_intf->type = lr_mod ? SOC_PORT_IF_LR : SOC_PORT_IF_SR; 1708 break; 1709 case SOC_PORT_IF_CR4: 1710 line_intf->type = lr_mod ? SOC_PORT_IF_LR4 : SOC_PORT_IF_SR4; 1711 break; 1712 default: 1713 intf_update = 0; 1714 break; 1715 } 1716 } 1717 if (intf_update) { 1718 SOC_IF_ERROR_RETURN(_phy_82328_intf_line_sys_update(unit, port)); 1719 } 1720 return SOC_E_NONE; 1721 } 1722 1723 STATIC int 1724 _phy_82328_mod_auto_detect_process(int unit, soc_port_t port, uint16 csr) 1725 { 1726 1727 LOG_ERROR(BSL_LS_SOC_PHY, 1728 (BSL_META_U(unit, 1729 "PHY82328 module detected: u=%d p=%d csr=%x\n"), 1730 unit, port, csr)); 1731 1732 /* 1733 * Speed cannot change with module detection so it must match the 1734 * currently configured speed 1735 */ 1736 if (!_phy_82328_mod_auto_detect_speed_check(unit, port, csr)) { 1737 return SOC_E_FAIL; 1738 } 1739 1740 /* 1741 * Get the line side interface based on the current interface and the 1742 * detected module 1743 */ 1744 SOC_IF_ERROR_RETURN(_phy_82328_mod_auto_detect_intf_process(unit, port, csr)); 1745 1746 return SOC_E_NONE; 1747 } 1748 1749 STATIC int 1750 _phy_82328_mod_auto_detect_update(int unit, soc_port_t port) 1751 { 1752 phy_ctrl_t *pc; 1753 uint16 ucode_csr; 1754 uint16 drv_csr; 1755 1756 pc = EXT_PHY_SW_STATE(unit, port); 1757 1758 /* 1759 * New module insertion when 1.c843[4] == 1 and 1.c841[4] == 0 1760 */ 1761 SOC_IF_ERROR_RETURN 1762 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REGISTER_3, &ucode_csr)); 1763 if (ucode_csr & MGT_TOP_PMD_USR_GP_REGISTER_3_SPEED_OR_TYPE_CHANGE_MASK) { 1764 SOC_IF_ERROR_RETURN 1765 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REGISTER_1, &drv_csr)); 1766 if (!(drv_csr & MGT_TOP_PMD_USR_GP_REGISTER_3_SPEED_OR_TYPE_CHANGE_MASK)) { 1767 SOC_IF_ERROR_RETURN(_phy_82328_mod_auto_detect_process(unit, port, ucode_csr)); 1768 1769 /* 1770 * Ack firmware that the module insertion has been updated 1771 * 1.c841[4] = 1, 1.c841[7] = 0 1772 */ 1773 SOC_IF_ERROR_RETURN 1774 (MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REGISTER_1, 1775 MGT_TOP_PMD_USR_GP_REGISTER_3_SPEED_OR_TYPE_CHANGE_MASK, 1776 MGT_TOP_PMD_USR_GP_REGISTER_3_SPEED_OR_TYPE_CHANGE_MASK | 1777 MGT_TOP_PMD_USR_GP_REGISTER_3_FINISH_CHANGE_MASK)); 1778 } 1779 } else { 1780 /* 1781 * New module removal when 1.c843[4] == 0 and 1.c841[4] == 1 1782 */ 1783 SOC_IF_ERROR_RETURN 1784 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REGISTER_1, &drv_csr)); 1785 if (drv_csr & MGT_TOP_PMD_USR_GP_REGISTER_3_SPEED_OR_TYPE_CHANGE_MASK) { 1786 /* 1787 * Ack firmware new module removal 1.c841[4] = 0 1788 */ 1789 SOC_IF_ERROR_RETURN 1790 (MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REGISTER_1, 1791 0, MGT_TOP_PMD_USR_GP_REGISTER_3_SPEED_OR_TYPE_CHANGE_MASK)); 1792 1793 LOG_ERROR(BSL_LS_SOC_PHY, 1794 (BSL_META_U(unit, 1795 "PHY82328 module removed u=%d p=%d\n"), unit, port)); 1796 } 1797 } 1798 1799 return SOC_E_NONE; 1800 } 1801 1802 /* 1803 * phy_82328_link_get 1804 * Purpose: 1805 * Get layer2 connection status. 1806 * Parameters: 1807 * unit - StrataSwitch unit #. 1808 * port - StrataSwitch port #. 1809 * link - address of memory to store link up/down state. 1810 * Returns: 1811 * SOC_E_NONE 1812 */ 1813 1814 STATIC int32 1815 phy_82328_link_get(int32 unit, soc_port_t port, int32 *link) 1816 { 1817 phy_ctrl_t *int_pc, *pc; 1818 int32 int_phy_link = 0; 1819 1820 if (link == NULL) { 1821 return SOC_E_PARAM; 1822 } 1823 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 1824 *link = FALSE; 1825 return SOC_E_NONE; 1826 } 1827 int_pc = INT_PHY_SW_STATE(unit, port); 1828 pc = EXT_PHY_SW_STATE(unit, port); 1829 1830 if (int_pc != NULL) { 1831 SOC_IF_ERROR_RETURN(PHY_LINK_GET(int_pc->pd, unit, port, &int_phy_link)); 1832 *link = int_phy_link; 1833 } else { 1834 *link = 1; 1835 } 1836 1837 SOC_IF_ERROR_RETURN( 1838 _phy_82328_intf_link_get( unit, port, link)); 1839 1840 if (MOD_AUTO_DETECT(pc)) { 1841 SOC_IF_ERROR_RETURN( 1842 _phy_82328_mod_auto_detect_update(unit, port)); 1843 } 1844 1845 LOG_VERBOSE(BSL_LS_SOC_PHY, 1846 (BSL_META_U(unit, 1847 "phy_82328_link_get: u=%d port%d: link:%s\n"), 1848 unit, port, *link ? "Up": "Down")); 1849 return SOC_E_NONE; 1850 } 1851 1852 /* 1853 * Function: 1854 * phy_82328_enable_set 1855 * Purpose: 1856 * Enable/Disable phy 1857 * Parameters: 1858 * unit - StrataSwitch unit #. 1859 * port - StrataSwitch port #. 1860 * enable - on/off state to set 1861 * Returns: 1862 * SOC_E_NONE 1863 */ 1864 1865 STATIC int32 1866 phy_82328_enable_set(int32 unit, soc_port_t port, int32 enable) 1867 { 1868 uint16 chan_data, chan_mask; 1869 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 1870 phy_ctrl_t *int_pc = INT_PHY_SW_STATE(unit, port); 1871 1872 /* Manually power channel up/down */ 1873 chan_data = enable ? 0 : 1874 (1 << MGT_TOP_PMD_USR_OPTICAL_CONFIGURATION_MAN_TXON_EN_SHIFT) | 1875 (1 << MGT_TOP_PMD_USR_OPTICAL_CONFIGURATION_TXOFFT_SHIFT); 1876 chan_mask = MGT_TOP_PMD_USR_OPTICAL_CONFIGURATION_MAN_TXON_EN_MASK | 1877 MGT_TOP_PMD_USR_OPTICAL_CONFIGURATION_TXOFFT_MASK; 1878 SOC_IF_ERROR_RETURN( 1879 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_OPTICAL_CONFIGURATION, 1880 chan_data, chan_mask)); 1881 if (enable) { 1882 SOC_IF_ERROR_RETURN(PHY_ENABLE_SET(int_pc->pd, unit, port, 1)); 1883 /* Let the micro settle down after powering back up */ 1884 sal_udelay(100); 1885 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE); 1886 PORT_DISABLED(pc) = 0; 1887 } else { 1888 SOC_IF_ERROR_RETURN(PHY_ENABLE_SET(int_pc->pd, unit, port, 0)); 1889 PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE); 1890 PORT_DISABLED(pc) = 1; 1891 } 1892 return SOC_E_NONE; 1893 } 1894 1895 /* 1896 * Function: 1897 * phy_82328_regbit_set_wait_check 1898 * Purpose: 1899 * Waits for a reg. bit to be set. 1900 * Spins until bit is set or time out. 1901 * The time out is programmable. 1902 * Parameters: 1903 * unit - StrataSwitch unit #. 1904 * port - StrataSwitch port #. 1905 * reg - register to test 1906 * bit_num - register bit to be tested 1907 * bitset - to test set/clear 1908 * timeout - spin time out 1909 * Returns: 1910 * SOC_E_NONE if no errors, SOC_E_ERROR else. 1911 */ 1912 STATIC 1913 int32 phy_82328_regbit_set_wait_check(int32 unit ,int32 port, 1914 int32 reg, /* register to check */ 1915 int32 bit_num, /* bit number to check */ 1916 int32 bitset, /* check bit set or bit clear */ 1917 int32 timeout) /* max wait time to check */ 1918 { 1919 uint16 data16 = 0; 1920 soc_timeout_t to; 1921 int32 rv; 1922 int32 cond; 1923 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 1924 1925 /* override min_polls with iteration count for DV. */ 1926 soc_timeout_init(&to, timeout, 0); 1927 do { 1928 rv = READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, reg, &data16); 1929 cond = (bitset && (data16 & bit_num)) || 1930 (!bitset && !(data16 & bit_num)); 1931 if (cond || (rv < 0)) { 1932 break; 1933 } 1934 } while (!soc_timeout_check(&to)); 1935 1936 /* Do one final check potentially after timeout as required by soc_timeout */ 1937 if (rv >= 0) { 1938 rv = READ_PHY82328_MMF_PMA_PMD_REG(unit,pc,reg,&data16); 1939 cond = (bitset && (data16 & bit_num)) || 1940 (!bitset && !(data16 & bit_num)); 1941 } 1942 return (cond? SOC_E_NONE: SOC_E_TIMEOUT); 1943 } 1944 1945 STATIC phy82328_intf_side_t 1946 _phy_82328_intf_side_regs_get(int32 unit, soc_port_t port) 1947 { 1948 int32 rv=0; 1949 uint16 data=0; 1950 phy82328_intf_side_t side = PHY82328_INTF_SIDE_LINE; 1951 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 1952 1953 rv = READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_XPMD_REGS_SEL, &data); 1954 if (rv == SOC_E_NONE) { 1955 side = (data & MGT_TOP_PMD_USR_XPMD_REGS_SEL_SELECT_SYS_REGISTERS_MASK) ? 1956 PHY82328_INTF_SIDE_SYS : PHY82328_INTF_SIDE_LINE; 1957 } 1958 return side; 1959 } 1960 1961 STATIC int32 1962 _phy_82328_intf_update(int32 unit, soc_port_t port, uint16 reg_data, uint16 reg_mask) 1963 { 1964 uint16 ucode_csr_bef; 1965 phy82328_intf_side_t saved_side; 1966 int32 rv = SOC_E_NONE; 1967 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 1968 1969 /* Access line side registers */ 1970 saved_side = _phy_82328_intf_side_regs_get(unit, port); 1971 if (saved_side == PHY82328_INTF_SIDE_SYS) { 1972 SOC_IF_ERROR_RETURN( 1973 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE)); 1974 } 1975 /* Make sure ucode has acked */ 1976 rv = READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REGISTER_3, &ucode_csr_bef); 1977 if (SOC_FAILURE(rv)) { 1978 LOG_ERROR(BSL_LS_SOC_PHY, 1979 (BSL_META_U(unit, 1980 "82328 failed reading ucode csr: u=%d p=%d err=%d\n"), 1981 unit, port, rv)); 1982 goto fail; 1983 } 1984 if ((ucode_csr_bef & MGT_TOP_PMD_USR_GP_REGISTER_3_FINISH_CHANGE_MASK) == 1985 MGT_TOP_PMD_USR_GP_REGISTER_3_FINISH_CHANGE_MASK) { 1986 1987 /* Cmd active and ucode acked, so let ucode know drv saw ack */ 1988 rv = MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REGISTER_1, 1989 0x0, MGT_TOP_PMD_USR_GP_REGISTER_1_FINISH_CHANGE_MASK); 1990 if (SOC_FAILURE(rv)) { 1991 LOG_ERROR(BSL_LS_SOC_PHY, 1992 (BSL_META_U(unit, 1993 "82328 failed clearing ack: u=%d p=%d err=%d\n"), 1994 unit, port, rv)); 1995 goto fail; 1996 } 1997 1998 /*Spin for finish Flag to Clear*/ 1999 rv = phy_82328_regbit_set_wait_check (unit,port,MGT_TOP_GP_REGISTER_3, 2000 MGT_TOP_PMD_USR_GP_REGISTER_3_FINISH_CHANGE_MASK,0,1000000); 2001 if (rv != SOC_E_NONE) { 2002 goto fail; 2003 } 2004 } 2005 LOG_INFO(BSL_LS_SOC_PHY, 2006 (BSL_META_U(unit, 2007 "82328 intf update register: u=%d, p=%d, 1.%04x=%04x/%04x ucode_csr=%04x\n"), 2008 unit, port, MGT_TOP_GP_REGISTER_1, reg_data, reg_mask, ucode_csr_bef)); 2009 2010 /* Send command */ 2011 rv = MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REGISTER_1, 2012 reg_data, reg_mask); 2013 if (SOC_FAILURE(rv)) { 2014 LOG_ERROR(BSL_LS_SOC_PHY, 2015 (BSL_META_U(unit, 2016 "82328 failed sending command to ucode: u=%d p=%d err=%d\n"), 2017 unit, port, rv)); 2018 goto fail; 2019 } 2020 /* Handshake with microcode by waiting for ack before moving on */ 2021 rv = phy_82328_regbit_set_wait_check (unit, port, MGT_TOP_GP_REGISTER_3, 2022 MGT_TOP_PMD_USR_GP_REGISTER_3_FINISH_CHANGE_MASK, 1, 1000000); 2023 2024 if (rv !=SOC_E_NONE) { 2025 goto fail; 2026 } 2027 /* Cmd active and ucode acked - let ucode know we saw ack */ 2028 rv = MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REGISTER_1, 2029 0, MGT_TOP_PMD_USR_GP_REGISTER_1_FINISH_CHANGE_MASK); 2030 if (rv != SOC_E_NONE) { 2031 goto fail; 2032 } 2033 2034 fail: 2035 if (saved_side == PHY82328_INTF_SIDE_SYS) { 2036 SOC_IF_ERROR_RETURN( 2037 phy82328_intf_side_reg_select (unit, port, PHY82328_INTF_SIDE_SYS)); 2038 } 2039 return rv; 2040 } 2041 2042 STATIC int32 2043 _phy_82328_intf_datapath_reg_get(int32 unit, soc_port_t port, phy82328_datapath_t datapath, 2044 uint16 *reg_data, uint16 *reg_mask) 2045 { 2046 *reg_data = 0; 2047 *reg_mask = 0; 2048 2049 switch (datapath) { 2050 case PHY82328_DATAPATH_20: 2051 *reg_data = 0; 2052 break; 2053 case PHY82328_DATAPATH_4_DEPTH_1: 2054 *reg_data = PHY82328_4BIT_DP_DEPTH1; 2055 break; 2056 case PHY82328_DATAPATH_4_DEPTH_2: 2057 *reg_data = PHY82328_4BIT_DP_DEPTH2; 2058 break; 2059 default : 2060 LOG_ERROR(BSL_LS_SOC_PHY, 2061 (BSL_META_U(unit, 2062 "82328 invalid datapath: u=%d p=%d datapath=%d\n"), 2063 unit, port, datapath)); 2064 return SOC_E_CONFIG; 2065 } 2066 *reg_data |= (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_FINISH_CHANGE_SHIFT); 2067 *reg_mask = (MGT_TOP_PMD_USR_GP_REGISTER_1_ENABLE_ULTRA_LOW_LATENCY_DATAPATH_MASK | 2068 MGT_TOP_PMD_USR_GP_REGISTER_1_ULL_DATAPATH_LATENCY_MASK | 2069 MGT_TOP_PMD_USR_GP_REGISTER_1_FINISH_CHANGE_MASK); 2070 2071 LOG_INFO(BSL_LS_SOC_PHY, 2072 (BSL_META_U(unit, 2073 "82328 datapath set register: u=%d, p=%d, reg=%04x/%04x, datapath=%d\n"), 2074 unit, port, *reg_data, *reg_mask, datapath)); 2075 return SOC_E_NONE; 2076 } 2077 2078 /* 2079 * Return the settings in gp_reg_1/gp_register_1 for the inteface speed 2080 * Register data and mask are returned to modify the register. 2081 */ 2082 STATIC int32 2083 _phy_82328_intf_speed_reg_get(int32 unit, soc_port_t port, int32 speed, uint16 *reg_data, uint16 *reg_mask) 2084 { 2085 *reg_data = 0; 2086 *reg_mask = 0; 2087 switch (speed) { 2088 case PHY82328_SPD_100G: /*1.C841.3 Not yet implemented */ 2089 *reg_data = PHY82328_GP_REG_1_SPD_100G; 2090 break; 2091 case PHY82328_SPD_42G:/*1.C841.[2-0]*/ 2092 *reg_data = PHY82328_GP_REG_1_SPD_42G; 2093 break; 2094 case PHY82328_SPD_40G:/*1.C841.2*/ 2095 *reg_data = PHY82328_GP_REG_1_SPD_40G; 2096 break; 2097 case PHY82328_SPD_11G: /*1.C841.0 & 1.C841.2*/ 2098 *reg_data = PHY82328_GP_REG_1_SPD_11G; 2099 break; 2100 case PHY82328_SPD_10G: /*1.C841.1*/ 2101 *reg_data = PHY82328_GP_REG_1_SPD_10G; 2102 break; 2103 case PHY82328_SPD_1G:/*1.C841.0*/ 2104 case 100: 2105 case 10: 2106 *reg_data = PHY82328_GP_REG_1_SPD_1G; 2107 break; 2108 default : 2109 LOG_ERROR(BSL_LS_SOC_PHY, 2110 (BSL_META_U(unit, 2111 "82328 invalid line speed %d: u=%d p=%d\n"), 2112 speed, unit, port)); 2113 return SOC_E_CONFIG; 2114 } 2115 *reg_data |= (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_FINISH_CHANGE_SHIFT); 2116 *reg_mask |= MGT_TOP_PMD_USR_GP_REGISTER_1_FINISH_CHANGE_MASK; 2117 *reg_mask |= (MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_1G_MASK | 2118 MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_10G_MASK| 2119 MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_40G_MASK | 2120 MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_100G_MASK); 2121 2122 LOG_INFO(BSL_LS_SOC_PHY, 2123 (BSL_META_U(unit, 2124 "82328 speed set register: u=%d, p=%d, reg=%04x/%04x), speed=%d\n"), 2125 unit, port, *reg_data, *reg_mask, speed)); 2126 return SOC_E_NONE; 2127 } 2128 2129 STATIC int32 2130 _phy_82328_intf_type_reg_get(int32 unit, soc_port_t port, soc_port_if_t intf_type, 2131 phy82328_intf_side_t side, uint16 *reg_data, uint16 *reg_mask) 2132 { 2133 uint16 data = 0; 2134 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 2135 2136 assert((side == PHY82328_INTF_SIDE_LINE) || (side == PHY82328_INTF_SIDE_SYS)); 2137 *reg_data = 0; 2138 *reg_mask = 0; 2139 2140 switch (intf_type) { 2141 case SOC_PORT_IF_KX: 2142 case SOC_PORT_IF_KR: 2143 case SOC_PORT_IF_KR4: 2144 data = (side == PHY82328_INTF_SIDE_SYS) ? 2145 (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_TYPE_SHIFT): 2146 (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_TYPE_SHIFT); 2147 *reg_mask |= (side == PHY82328_INTF_SIDE_SYS) ? 2148 (MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_TYPE_MASK): 2149 (MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_TYPE_MASK); 2150 break; 2151 case SOC_PORT_IF_SR: 2152 case SOC_PORT_IF_SFI:/*Nothing but 10G, but not in list*/ 2153 case SOC_PORT_IF_GMII: 2154 case SOC_PORT_IF_SGMII: 2155 case SOC_PORT_IF_SR4: 2156 data = 0; 2157 break; 2158 case SOC_PORT_IF_CR4: 2159 /* If CR4 line side and autoneg enabled, then CR4, otherwise, XFI/XLAUI_DFE*/ 2160 if (side == PHY82328_INTF_SIDE_LINE) { 2161 data = (AN_EN(pc)) ? (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_CU_TYPE_SHIFT) : 2162 ((1 << MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_FORCED_CL72_MODE_SHIFT) | 2163 (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_CU_TYPE_SHIFT)); 2164 } else { 2165 /*System side set to XLAUI_DFE */ 2166 /*CR4 System side is unusual taken 2167 CL72 not supported for Sys Side only DFE*/ 2168 data = (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_FORCED_CL72_MODE_SHIFT) | 2169 (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_CU_TYPE_SHIFT); 2170 } 2171 break; 2172 case SOC_PORT_IF_CR: 2173 data = (side == PHY82328_INTF_SIDE_SYS) ? 2174 ((1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_FORCED_CL72_MODE_SHIFT) | 2175 (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_CU_TYPE_SHIFT)) : 2176 (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_CU_TYPE_SHIFT); 2177 break; 2178 case SOC_PORT_IF_XFI: 2179 case SOC_PORT_IF_XLAUI: 2180 data = (side == PHY82328_INTF_SIDE_SYS) ? 2181 ((1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_LR_MODE_SHIFT) | 2182 (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_CU_TYPE_SHIFT)) : 2183 ((1 << MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_LR_MODE_SHIFT) | 2184 (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_CU_TYPE_SHIFT)); 2185 break; 2186 2187 case SOC_PORT_IF_LR: 2188 case SOC_PORT_IF_LR4: 2189 data = (side == PHY82328_INTF_SIDE_SYS) ? 2190 (1<< MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_LR_MODE_SHIFT) : 2191 (1<< MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_LR_MODE_SHIFT); 2192 break; 2193 default: 2194 LOG_ERROR(BSL_LS_SOC_PHY, 2195 (BSL_META_U(unit, 2196 "82328 Unsupported interface: u=%d p=%d\n"), unit, port)); 2197 return SOC_E_UNAVAIL; 2198 } 2199 *reg_data |= (data | (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_FINISH_CHANGE_SHIFT)); 2200 *reg_mask |= MGT_TOP_PMD_USR_GP_REGISTER_1_FINISH_CHANGE_MASK; 2201 if (side == PHY82328_INTF_SIDE_LINE) { 2202 *reg_mask |= (MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_LR_MODE_MASK | 2203 MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_FORCED_CL72_MODE_MASK | 2204 MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_CU_TYPE_MASK | 2205 MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_TYPE_MASK); 2206 } else { 2207 /* System side mask */ 2208 *reg_mask |= (MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_LR_MODE_MASK | 2209 MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_FORCED_CL72_MODE_MASK | 2210 MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_CU_TYPE_MASK | 2211 MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_TYPE_MASK); 2212 } 2213 LOG_INFO(BSL_LS_SOC_PHY, 2214 (BSL_META_U(unit, 2215 "82328 intf type register: u=%d, p=%d, reg=%04x/%04x, intf=%d\n"), 2216 unit, port, *reg_data, *reg_mask, intf_type)); 2217 2218 return SOC_E_NONE; 2219 } 2220 2221 STATIC int32 2222 _phy_82328_intf_debug_print(int32 unit, soc_port_t port, const char *msg) 2223 { 2224 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT) 2225 phy_ctrl_t *pc; 2226 phy82328_intf_cfg_t *line_intf, *sys_intf; 2227 2228 pc = EXT_PHY_SW_STATE(unit, port); 2229 line_intf = &(LINE_INTF(pc)); 2230 sys_intf = &(SYS_INTF(pc)); 2231 2232 LOG_INFO(BSL_LS_SOC_PHY, 2233 (BSL_META_U(unit, 2234 "%s: "), msg)); 2235 LOG_INFO(BSL_LS_SOC_PHY, 2236 (BSL_META_U(unit, 2237 "[LINE:intf=%s,speed=%d], "), 2238 phy82328_intf_names[line_intf->type], line_intf->speed)); 2239 LOG_INFO(BSL_LS_SOC_PHY, 2240 (BSL_META_U(unit, 2241 "[SYS :intf=%s,speed=%d]\n"), 2242 phy82328_intf_names[sys_intf->type], sys_intf->speed)); 2243 #endif /* BROADCOM_DEBUG || DEBUG_PRINT */ 2244 return SOC_E_NONE; 2245 } 2246 2247 2248 STATIC int32 2249 _phy_82328_intf_line_sys_update(int32 unit, soc_port_t port) 2250 { 2251 phy_ctrl_t *pc; 2252 phy_ctrl_t *int_pc; 2253 uint16 data = 0, mask = 0; 2254 uint16 reg_data = 0, reg_mask = 0; 2255 int32 int_phy_en = 0; 2256 phy82328_intf_cfg_t *line_intf, *sys_intf; 2257 2258 pc = EXT_PHY_SW_STATE(unit, port); 2259 int_pc = INT_PHY_SW_STATE(unit, port); 2260 line_intf = &(LINE_INTF(pc)); 2261 sys_intf = &(SYS_INTF(pc)); 2262 2263 _phy_82328_intf_debug_print(unit, port, "interface/Speed update"); 2264 2265 reg_data = 0; 2266 reg_mask = 0; 2267 SOC_IF_ERROR_RETURN( 2268 _phy_82328_intf_type_reg_get(unit, port, line_intf->type, 2269 PHY82328_INTF_SIDE_LINE, &data, &mask)); 2270 reg_data |= data; 2271 reg_mask |= mask; 2272 2273 SOC_IF_ERROR_RETURN( 2274 _phy_82328_intf_type_reg_get(unit, port, sys_intf->type, 2275 PHY82328_INTF_SIDE_SYS, &data, &mask)); 2276 reg_data |= data; 2277 reg_mask |= mask; 2278 2279 LOG_INFO(BSL_LS_SOC_PHY, 2280 (BSL_META_U(unit, 2281 "82328 intf update: line=%s sys=%s speed=%d (1.%x = %04x/%04x): u=%d p=%d\n"), 2282 phy82328_intf_names[line_intf->type], phy82328_intf_names[sys_intf->type], 2283 line_intf->speed, MGT_TOP_GP_REGISTER_1, reg_data, reg_mask, 2284 unit, port)); 2285 2286 SOC_IF_ERROR_RETURN( 2287 _phy_82328_intf_speed_reg_get(unit, port, line_intf->speed, &data, &mask)); 2288 reg_data |= data; 2289 reg_mask |= mask; 2290 2291 SOC_IF_ERROR_RETURN( 2292 _phy_82328_intf_datapath_reg_get(unit, port, CUR_DATAPATH(pc), &data, &mask)); 2293 reg_data |= data; 2294 reg_mask |= mask; 2295 2296 LOG_INFO(BSL_LS_SOC_PHY, 2297 (BSL_META_U(unit, 2298 "82328 intf update: line=%s sys=%s speed=%d (1.%x = %04x/%04x): u=%d p=%d\n"), 2299 phy82328_intf_names[line_intf->type], phy82328_intf_names[sys_intf->type], 2300 line_intf->speed, MGT_TOP_GP_REGISTER_1, reg_data, reg_mask, 2301 unit, port)); 2302 2303 if (SYNC_INIT(pc) == 1) { 2304 SOC_IF_ERROR_RETURN(PHY_ENABLE_GET(int_pc->pd, unit, port, &int_phy_en)); 2305 if (int_phy_en) { 2306 /* Turn off internal PHY while the mode changes */ 2307 SOC_IF_ERROR_RETURN(PHY_ENABLE_SET(int_pc->pd, unit, port, 0)); 2308 } 2309 } 2310 /* GP registers are only on the line side */ 2311 SOC_IF_ERROR_RETURN(_phy_82328_intf_update(unit, port, reg_data, reg_mask)); 2312 2313 if (SYNC_INIT(pc) == 1) { 2314 if (int_phy_en) { 2315 /* If called from PASS2 we skip this and complete in PASS3 */ 2316 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2)) { 2317 INT_PHY_RE_EN(pc) = 1; 2318 /* start timer */ 2319 soc_timeout_init(&SYNC_TO(pc), 10000, 0); 2320 } else { 2321 sal_udelay(10000); 2322 /* Turn internal PHY back on now that the mode has been configured */ 2323 SOC_IF_ERROR_RETURN(PHY_ENABLE_SET(int_pc->pd, unit, port, 1)); 2324 } 2325 } 2326 } 2327 return SOC_E_NONE; 2328 } 2329 2330 2331 /* 2332 * Return whether AN is enabled or forced with internal SerDes on the system side 2333 */ 2334 STATIC int32 2335 _phy_82328_intf_sys_forced(int32 unit, soc_port_t port, soc_port_if_t intf_type) 2336 { 2337 int32 rv; 2338 phy_ctrl_t *pc; 2339 2340 pc = EXT_PHY_SW_STATE(unit, port); 2341 2342 switch (intf_type) { 2343 case SOC_PORT_IF_SR: 2344 case SOC_PORT_IF_SR4: 2345 case SOC_PORT_IF_LR: 2346 case SOC_PORT_IF_LR4: 2347 case SOC_PORT_IF_XLAUI: 2348 case SOC_PORT_IF_XFI: 2349 case SOC_PORT_IF_SFI: 2350 case SOC_PORT_IF_CR: 2351 case SOC_PORT_IF_CR4: 2352 case SOC_PORT_IF_ZR: 2353 rv = TRUE; 2354 break; 2355 case SOC_PORT_IF_GMII: 2356 rv = FALSE; 2357 break; 2358 case SOC_PORT_IF_KR: 2359 case SOC_PORT_IF_KR4: 2360 rv = SYS_FORCED_CL72(pc) ? TRUE : FALSE; 2361 break; 2362 default: 2363 rv = FALSE; 2364 } 2365 return rv; 2366 } 2367 2368 STATIC int32 2369 _phy_82328_speed_set(int32 unit, soc_port_t port, int32 speed) 2370 { 2371 int rv = SOC_E_NONE; 2372 int cur_speed = 0; 2373 uint32 cur_fw_mode = 0; 2374 int32 cur_an, cur_an_done; 2375 soc_port_if_t cur_type, new_type; 2376 phy_ctrl_t *pc, *int_pc; 2377 phy82328_intf_cfg_t *line_intf; 2378 phy82328_intf_cfg_t *sys_intf; 2379 2380 pc = EXT_PHY_SW_STATE(unit, port); 2381 int_pc = INT_PHY_SW_STATE(unit, port); 2382 line_intf = &(LINE_INTF(pc)); 2383 sys_intf = &(SYS_INTF(pc)); 2384 2385 line_intf->speed = speed; 2386 sys_intf->speed = speed; 2387 2388 if (int_pc != NULL) { 2389 if ((sys_intf->type == SOC_PORT_IF_GMII) || (sys_intf->type == SOC_PORT_IF_SGMII)) { 2390 SOC_IF_ERROR_RETURN(PHY_SPEED_SET(int_pc->pd, unit, port, sys_intf->speed)); 2391 } else if (_phy_82328_intf_sys_forced(unit, port, sys_intf->type) ) { 2392 /* 2393 * When setting system side 40G DAC/XLAUI-DFE, tell internal SerDes to match 2394 * with XLAUI. 2395 * 2396 * If flexports, the internal SerDes may be out of sync until it gets a chance 2397 * to convert the port, so these operations may be best effort. 2398 */ 2399 /* When the speed is 20G forcing interface to MLD irrespective of 2400 * remote PHY capability. When remote PHY capablity is enabled 2401 * forcing interface and speed */ 2402 new_type = (sys_intf->type == SOC_PORT_IF_CR4) ? SOC_PORT_IF_XLAUI : sys_intf->type; 2403 SOC_IF_ERROR_RETURN(PHY_INTERFACE_GET(int_pc->pd, unit, port, &cur_type)); 2404 if (cur_type != new_type) { 2405 (void) PHY_INTERFACE_SET(int_pc->pd, unit, port, new_type); 2406 } 2407 2408 /* Check if it must change to forced */ 2409 SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_GET(int_pc->pd, unit, port, &cur_an, &cur_an_done)); 2410 if (cur_an == TRUE) { 2411 (void) PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit,port, FALSE); 2412 } 2413 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2)) { 2414 /* Skip int_pc speed set during phy init */ 2415 } else if ((rv = PHY_SPEED_GET(int_pc->pd, unit, port, &cur_speed)) 2416 != SOC_E_NONE) { 2417 #if 0 2418 LOG_CLI((BSL_META_U(unit, 2419 "82328 u=%d p=%d speed get error\n"), unit, port)); 2420 #endif 2421 return rv; 2422 } else if (cur_speed != sys_intf->speed) { 2423 (void) PHY_SPEED_SET(int_pc->pd, unit, port, sys_intf->speed); 2424 } 2425 2426 /* For system intf=cr4 use XLAUI_DFE on Serdes (in forced mode)*/ 2427 if (sys_intf->type != SOC_PORT_IF_CR4) { 2428 /* Skip int_pc fw mode set */ 2429 } else if ((rv = PHY_CONTROL_GET(int_pc->pd, unit, port, 2430 SOC_PHY_CONTROL_FIRMWARE_MODE, &cur_fw_mode)) 2431 != SOC_E_NONE) { 2432 return rv; 2433 } else if (cur_fw_mode != SOC_PHY_FIRMWARE_FORCE_OSDFE) { 2434 (void) PHY_CONTROL_SET(int_pc->pd, unit, port, 2435 SOC_PHY_CONTROL_FIRMWARE_MODE, 2436 SOC_PHY_FIRMWARE_FORCE_OSDFE); 2437 } 2438 2439 } else { 2440 SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit,port, TRUE)); 2441 } 2442 } 2443 /* Update interface type/speed */ 2444 return (_phy_82328_intf_line_sys_update(unit, port)); 2445 } 2446 /* 2447 * Function: 2448 * _phy_82328_intf_type_1G 2449 * Purpose: 2450 * Check the interface for 1G 2451 * Parameters: 2452 * unit - StrataSwitch unit #. 2453 * port - StrataSwitch port #. 2454 * intf_type - Interface type to test 2455 * Returns: 2456 * TRUE/FALSE 2457 */ 2458 STATIC int32 2459 _phy_82328_intf_type_1G(soc_port_if_t intf_type) 2460 { 2461 int32 rv; 2462 2463 switch (intf_type) { 2464 case SOC_PORT_IF_KX: 2465 case SOC_PORT_IF_GMII: 2466 case SOC_PORT_IF_SGMII: 2467 rv = TRUE; 2468 break; 2469 default: 2470 rv = FALSE; 2471 } 2472 return rv; 2473 } 2474 2475 /* 2476 * Function: 2477 * _phy_82328_intf_type_10G 2478 * Purpose: 2479 * Check the interface for 10G 2480 * Parameters: 2481 * unit - StrataSwitch unit #. 2482 * port - StrataSwitch port #. 2483 * intf_type - Interface type to test 2484 * Returns: 2485 * TRUE/FALSE 2486 */ 2487 STATIC int32 2488 _phy_82328_intf_type_10G(soc_port_if_t intf_type) 2489 { 2490 int32 rv; 2491 2492 switch (intf_type) { 2493 case SOC_PORT_IF_SR: 2494 case SOC_PORT_IF_CR: 2495 case SOC_PORT_IF_LR: 2496 case SOC_PORT_IF_KR: 2497 case SOC_PORT_IF_ZR: 2498 case SOC_PORT_IF_XFI: 2499 case SOC_PORT_IF_SFI: 2500 rv = TRUE; 2501 break; 2502 default: 2503 rv = FALSE; 2504 } 2505 return rv; 2506 } 2507 2508 2509 STATIC int32 2510 _phy_82328_intf_line_sys_init(int32 unit, soc_port_t port) 2511 { 2512 phy_ctrl_t *pc; 2513 phy82328_intf_cfg_t *line_intf; 2514 2515 pc = EXT_PHY_SW_STATE(unit, port); 2516 line_intf = &(LINE_INTF(pc)); 2517 2518 return _phy_82328_speed_set(unit, port, line_intf->speed); 2519 } 2520 2521 /* 2522 * Function: 2523 * phy_82328_speed_set 2524 * Purpose: 2525 * Set PHY speed 2526 * For 20G speed make sure serdes configured as 20G MLD 2527 * Parameters: 2528 * unit - StrataSwitch unit #. 2529 * port - StrataSwitch port #. 2530 * speed - link speed in Mbps 2531 * Returns: 2532 * SOC_E_NONE 2533 */ 2534 2535 STATIC int32 2536 phy_82328_speed_set(int32 unit, soc_port_t port, int32 speed) 2537 { 2538 int32 rv; 2539 phy_ctrl_t *pc; 2540 phy82328_intf_cfg_t *line_intf; 2541 phy82328_intf_cfg_t *sys_intf; 2542 2543 COMPILER_REFERENCE(unit); 2544 COMPILER_REFERENCE(port); 2545 2546 pc = EXT_PHY_SW_STATE(unit, port); 2547 line_intf = &(LINE_INTF(pc)); 2548 sys_intf = &(SYS_INTF(pc)); 2549 2550 LOG_INFO(BSL_LS_SOC_PHY, 2551 (BSL_META_U(unit, 2552 "phy_82328_speed_set: u=%d p=%d speed=%d\n"), 2553 unit, port,speed)); 2554 if (PHY82328_SINGLE_PORT_MODE(pc)) { 2555 if (!_phy_82328_intf_is_single_port(line_intf->type)) { 2556 LOG_INFO(BSL_LS_SOC_PHY, 2557 (BSL_META_U(unit, 2558 "82328 speed set does not match interface: " 2559 "u=%d p=%d speed=%d intf=%d\n"), 2560 unit, port, speed, sys_intf->type)); 2561 return SOC_E_PARAM; 2562 } 2563 /*Single port mode can supported 40/40HG/42HG/100G*/ 2564 switch (speed) { 2565 case PHY82328_SPD_40G: 2566 /* Both 40G And 40HG share same 2567 * register config */ 2568 break; 2569 case PHY82328_SPD_42G: 2570 if (! IS_HG_PORT(unit, port)) { 2571 speed = PHY82328_SPD_40G; 2572 } 2573 break; 2574 case PHY82328_SPD_100G: 2575 break; 2576 default: 2577 LOG_ERROR(BSL_LS_SOC_PHY, 2578 (BSL_META_U(unit, 2579 "82328 invalid speed Single Port: u=%d p=%d speed=%d\n"), 2580 unit, port, speed)); 2581 return SOC_E_PARAM; 2582 } 2583 } else { 2584 /*Check for the valid interface*/ 2585 if(_phy_82328_intf_is_single_port(line_intf->type)){ 2586 LOG_ERROR(BSL_LS_SOC_PHY, 2587 (BSL_META_U(unit, 2588 "82328 invalid intf in quad port: u=%d p=%d intf=%d\n"), 2589 unit, port, line_intf->type)); 2590 return SOC_E_PARAM; 2591 } 2592 switch (speed) { 2593 case PHY82328_SPD_1G: 2594 if(!_phy_82328_intf_type_1G(line_intf->type)){ 2595 line_intf->type = SOC_PORT_IF_GMII; 2596 } 2597 /* 2598 * Changing speed to 1000 2599 * - if backplane interface(KR) then change to KX 2600 * - if not KX, then set to GMII 2601 */ 2602 if (sys_intf->type == SOC_PORT_IF_KR) { 2603 sys_intf->type = SOC_PORT_IF_KX; 2604 } else if (sys_intf->type != SOC_PORT_IF_KX) { 2605 sys_intf->type = line_intf->type; 2606 } 2607 break; 2608 case 100: 2609 case 10: 2610 if (line_intf->type != SOC_PORT_IF_SGMII) { 2611 line_intf->type = SOC_PORT_IF_SGMII; 2612 } 2613 sys_intf->type = line_intf->type; 2614 break; 2615 2616 /*10G/11G LR/SR/CR XFI/XFI DFE/Forced CL72*/ 2617 case PHY82328_SPD_11G: 2618 /* 11G only valid for HG[11] */ 2619 if (!IS_HG_PORT(unit, port)) { 2620 speed = PHY82328_SPD_10G; 2621 } 2622 break; 2623 case PHY82328_SPD_10G: 2624 /* If changing from 1000 to 10000/11000, then adjust interface*/ 2625 if (line_intf->speed <= PHY82328_SPD_1G) { 2626 /* If changing speed from 1000 to 10000, set line interface to SR*/ 2627 if (!_phy_82328_intf_type_10G(line_intf->type)) { 2628 line_intf->type = SOC_PORT_IF_SR; 2629 } 2630 if (!_phy_82328_intf_type_10G(sys_intf->type)) { 2631 sys_intf->type = SOC_PORT_IF_XFI; 2632 } 2633 } 2634 break; 2635 case PHY82328_SPD_40G: 2636 case PHY82328_SPD_42G:/*42G*/ 2637 case PHY82328_SPD_100G: 2638 default: 2639 LOG_ERROR(BSL_LS_SOC_PHY, 2640 (BSL_META_U(unit, 2641 "82328 invalid speed Quad Port: u=%d p=%d speed=%d\n"), 2642 unit, port, speed)); 2643 return SOC_E_PARAM; 2644 } 2645 } 2646 2647 rv = _phy_82328_speed_set(unit, port, speed); 2648 if (SOC_FAILURE(rv)) { 2649 LOG_ERROR(BSL_LS_SOC_PHY, 2650 (BSL_META_U(unit, 2651 "82328 %s failed: u=%d p=%d\n"), FUNCTION_NAME(), unit, port)); 2652 } 2653 return rv; 2654 } 2655 2656 /* 2657 * Function: 2658 * phy_82328_speed_get 2659 * Purpose: 2660 * Get PHY speed 2661 * Parameters: 2662 * unit - StrataSwitch unit #. 2663 * port - StrataSwitch port #. 2664 * speed - current link speed in Mbps 2665 * Returns: 2666 * SOC_E_NONE 2667 */ 2668 2669 STATIC int32 2670 phy_82328_speed_get(int32 unit, soc_port_t port, int32 *speed) 2671 { 2672 phy82328_intf_cfg_t *line_intf; 2673 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 2674 2675 if ((pc !=NULL )&& (speed !=NULL)) { 2676 line_intf = &(LINE_INTF(pc)); 2677 *speed = line_intf->speed; 2678 } else { 2679 return SOC_E_PARAM; 2680 } 2681 return SOC_E_NONE; 2682 } 2683 2684 /* 2685 * Directly select channel to access based on interface side and lane number. 2686 */ 2687 STATIC int32 2688 _phy_82328_channel_direct_select(int32 unit, soc_port_t port, phy82328_intf_side_t side, int32 lane) 2689 { 2690 uint16 lane_sel; 2691 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 2692 2693 /* 2694 * If all lanes, restore single PMD access with lane 0 broadcast to all lanes 2695 * For single lane, select lane in Single PMD 1.ca86[5:4] and [3..0] that corresponds 2696 * to the lane with direct lane selection in 1.ca86[8] 2697 */ 2698 if (lane == PHY82328_ALL_LANES) { 2699 lane_sel = 2700 (LOGICAL_LANE0(pc) << MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_PHY_CH_TO_ACCESS_IN_SINGLE_PMD_SHIFT) | 2701 MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_SINGLE_PMD_MODE_MASK | 2702 MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_PHY_CH_TO_BE_DISABLE_IN_SINGLE_PMD_MASK; 2703 } else { 2704 lane_sel = (lane << MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_PHY_CH_TO_ACCESS_IN_SINGLE_PMD_SHIFT) | 2705 ((1 << lane) & MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_PHY_CH_TO_BE_DISABLE_IN_SINGLE_PMD_MASK); 2706 } 2707 SOC_IF_ERROR_RETURN( 2708 _phy_82328_modify_pma_pmd_reg (unit, port, pc, 2709 PHY82328_DEV_PMA_PMD, MGT_TOP_SINGLE_PMD_CTRL, 2710 MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_PHY_CH_TO_BE_DISABLE_IN_SINGLE_PMD_SHIFT +3/*+ 5*/, 2711 MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_PHY_CH_TO_BE_DISABLE_IN_SINGLE_PMD_SHIFT, lane_sel)); 2712 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 0xca86, &lane_sel); 2713 return SOC_E_NONE; 2714 } 2715 2716 /* 2717 * Select channel to access based on interface side and lane number. 2718 * The side is selected before returning. 2719 */ 2720 STATIC int32 2721 _phy_82328_channel_select(int32 unit, soc_port_t port, phy82328_intf_side_t side, int32 lane) 2722 { 2723 int32 rv; 2724 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 2725 2726 if (!(PHY82328_SINGLE_PORT_MODE(pc))) { 2727 return SOC_E_PARAM; 2728 } 2729 2730 if (!((lane == PHY82328_ALL_LANES) || ((lane >= 0) && (lane <= 3)))) { 2731 return SOC_E_PARAM; 2732 } 2733 SOC_IF_ERROR_RETURN( 2734 phy82328_intf_side_reg_select(unit, port, side)); 2735 2736 rv = _phy_82328_channel_direct_select(unit, port, side, lane); 2737 2738 return rv; 2739 } 2740 2741 /* 2742 * 20-bit: set txpol in line side 1.DOE3[0] 2743 * 4-bit: set txpol in line side 1.D0A0[9] 2744 */ 2745 STATIC int32 2746 _phy_82328_polarity_flip_tx_set(int32 unit, soc_port_t port, int32 flip) 2747 { 2748 uint16 data = 0; 2749 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 2750 2751 /* Clear to flip, set to unflip */ 2752 if (CUR_DATAPATH(pc) == PHY82328_DATAPATH_20) { 2753 data = flip ? TLB_RX_TLB_RX_MISC_CONFIG_RX_PMD_DP_INVERT_MASK : 0; 2754 SOC_IF_ERROR_RETURN( 2755 _phy_82328_modify_pma_pmd_reg (unit, port, pc, 2756 PHY82328_DEV_PMA_PMD, TLB_TX_TLB_TX_MISC_CONFIG, 2757 TLB_TX_TLB_TX_MISC_CONFIG_TX_PMD_DP_INVERT_SHIFT, 2758 TLB_TX_TLB_TX_MISC_CONFIG_TX_PMD_DP_INVERT_SHIFT, data)); 2759 } else { 2760 data = flip ? 1 : 0; 2761 SOC_IF_ERROR_RETURN( 2762 _phy_82328_modify_pma_pmd_reg (unit, port, pc, 2763 PHY82328_DEV_PMA_PMD, AMS_TX_TX_CTRL_0, 2764 AMS_TX_TX_CTRL_0_LL_POLARITY_FLIP_SHIFT, 2765 AMS_TX_TX_CTRL_0_LL_POLARITY_FLIP_SHIFT, data)); 2766 } 2767 return SOC_E_NONE; 2768 } 2769 2770 STATIC int32 2771 _phy_82328_polarity_flip_tx(int32 unit, soc_port_t port, phy82328_intf_side_t side, uint16 cfg_pol) 2772 { 2773 int32 flip; 2774 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 2775 int32 lane = 0; 2776 2777 if (side != PHY82328_INTF_SIDE_LINE) { 2778 SOC_IF_ERROR_RETURN( 2779 phy82328_intf_side_reg_select(unit, port, side)); 2780 } 2781 if ((PHY82328_SINGLE_PORT_MODE(pc))) { 2782 if (cfg_pol != PHY82328_POL_DND) { 2783 for (lane = 0; lane < PHY82328_NUM_LANES; lane++) { 2784 /* Check for all lanes or whether this lane has polarity flipped */ 2785 if ((cfg_pol & POL_CONFIG_LANE_MASK(lane)) == POL_CONFIG_LANE_MASK(lane)) { 2786 flip = 1; 2787 } else { 2788 flip = 0; 2789 } 2790 LOG_INFO(BSL_LS_SOC_PHY, 2791 (BSL_META_U(unit, 2792 "82328 tx polarity flip=%d: u=%d p=%d" 2793 "lane=%d\n"), flip, unit, port, lane)); 2794 2795 /* Select the lane on the line side */ 2796 SOC_IF_ERROR_RETURN 2797 (_phy_82328_channel_select(unit, port, side, lane)); 2798 SOC_IF_ERROR_RETURN 2799 (_phy_82328_polarity_flip_tx_set(unit, port, flip)); 2800 } 2801 /* Restore to default single port register access */ 2802 SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, PHY82328_INTF_SIDE_LINE, 2803 PHY82328_ALL_LANES)); 2804 } 2805 } 2806 else { /* quad mode */ 2807 if (cfg_pol != PHY82328_POL_DND) { 2808 flip = (cfg_pol) ? 1 : 0; 2809 SOC_IF_ERROR_RETURN 2810 (_phy_82328_polarity_flip_tx_set(unit, port, flip)); 2811 LOG_INFO(BSL_LS_SOC_PHY, 2812 (BSL_META_U(unit, 2813 "82328 polarity flip: u=%d p=%d\n"), unit, port)); 2814 } 2815 } 2816 if (side != PHY82328_INTF_SIDE_LINE) { 2817 SOC_IF_ERROR_RETURN( 2818 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE)); 2819 } 2820 2821 return SOC_E_NONE; 2822 } 2823 2824 STATIC int32 2825 _phy_82328_polarity_flip_rx_20bit(int32 unit, soc_port_t port, int32 flip) 2826 { 2827 uint16 data = 0; 2828 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 2829 2830 data = flip ? 1 : 0; 2831 SOC_IF_ERROR_RETURN( 2832 _phy_82328_modify_pma_pmd_reg (unit, port, pc, 2833 PHY82328_DEV_PMA_PMD, TLB_RX_TLB_RX_MISC_CONFIG, 2834 TLB_RX_TLB_RX_MISC_CONFIG_RX_PMD_DP_INVERT_SHIFT, 2835 TLB_RX_TLB_RX_MISC_CONFIG_RX_PMD_DP_INVERT_SHIFT, data)); 2836 2837 return SOC_E_NONE; 2838 } 2839 2840 STATIC int32 2841 _phy_82328_polarity_flip_rx(int32 unit, soc_port_t port, phy82328_intf_side_t side, uint16 cfg_pol) 2842 { 2843 int32 flip; 2844 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 2845 int32 lane; 2846 2847 if (side != PHY82328_INTF_SIDE_LINE) { 2848 SOC_IF_ERROR_RETURN( 2849 phy82328_intf_side_reg_select(unit, port, side)); 2850 } 2851 if ((PHY82328_SINGLE_PORT_MODE(pc))) { 2852 if (cfg_pol != PHY82328_POL_DND) { 2853 /* 4-bit polarity handled on system side */ 2854 if (CUR_DATAPATH(pc) != PHY82328_DATAPATH_20) { 2855 PHY_82328_MICRO_PAUSE(unit, port, "polarity rx"); 2856 } 2857 for (lane = 0; lane < PHY82328_NUM_LANES; lane++) { 2858 flip = 0; 2859 if ((cfg_pol & POL_CONFIG_LANE_MASK(lane)) == POL_CONFIG_LANE_MASK(lane)) { 2860 flip = 1; 2861 } 2862 if (CUR_DATAPATH(pc) == PHY82328_DATAPATH_20) { 2863 SOC_IF_ERROR_RETURN 2864 (_phy_82328_channel_select(unit, port, side, lane)); 2865 SOC_IF_ERROR_RETURN 2866 (_phy_82328_polarity_flip_rx_20bit(unit, port, flip)); 2867 } 2868 LOG_INFO(BSL_LS_SOC_PHY, 2869 (BSL_META_U(unit, 2870 "82328 rx polarity flip: u=%d p=%d lane=%d\n"), unit, port, lane)); 2871 } 2872 /* Restore to default single port register access */ 2873 SOC_IF_ERROR_RETURN 2874 (_phy_82328_channel_select(unit, port, PHY82328_INTF_SIDE_LINE, PHY82328_ALL_LANES)); 2875 if (CUR_DATAPATH(pc) != PHY82328_DATAPATH_20) { 2876 PHY_82328_MICRO_RESUME(unit, port); 2877 } 2878 } 2879 } 2880 2881 else { /* quad mode */ 2882 if (cfg_pol != PHY82328_POL_DND) { 2883 flip = (cfg_pol)? 1:0; 2884 SOC_IF_ERROR_RETURN(_phy_82328_polarity_flip_rx_20bit(unit, port, flip)); 2885 } 2886 } 2887 2888 if (side != PHY82328_INTF_SIDE_LINE) { 2889 SOC_IF_ERROR_RETURN( 2890 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE)); 2891 } 2892 2893 LOG_INFO(BSL_LS_SOC_PHY, 2894 (BSL_META_U(unit, 2895 "82328 rx polarity flip: u=%d p=%d\n"), unit, port)); 2896 return SOC_E_NONE; 2897 } 2898 2899 /* 2900 * Flip configured tx/rx polarities 2901 * 2902 * Property values are either 1 for all lanes or 2903 * lane 0: 0001 2904 * lane 1: 0002 2905 * lane 2: 0004 2906 * lane 3: 0008 2907 */ 2908 STATIC int32 2909 _phy_82328_polarity_flip(int32 unit, soc_port_t port, uint16 cfg_tx_pol, uint16 cfg_rx_pol) 2910 { 2911 LOG_INFO(BSL_LS_SOC_PHY, 2912 (BSL_META_U(unit, 2913 "82328 polarity flip: u=%d p%d TX=%x RX=%x\n"), unit, port, 2914 cfg_tx_pol, cfg_rx_pol)); 2915 if (cfg_tx_pol != PHY82328_POL_DND) { 2916 SOC_IF_ERROR_RETURN( 2917 _phy_82328_polarity_flip_tx(unit, port, PHY82328_INTF_SIDE_LINE, cfg_tx_pol)); 2918 } 2919 if (cfg_rx_pol != PHY82328_POL_DND) { 2920 SOC_IF_ERROR_RETURN( 2921 _phy_82328_polarity_flip_rx(unit, port, PHY82328_INTF_SIDE_LINE, cfg_rx_pol)); 2922 } 2923 2924 return SOC_E_NONE; 2925 } 2926 2927 STATIC void 2928 _phy_82328_micro_pause(int32 unit, soc_port_t port, const char *loc) 2929 { 2930 int32 rv = SOC_E_NONE; 2931 uint16 data, mask; 2932 int32 checks; 2933 uint16 csr; 2934 uint16 saved_side; 2935 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 2936 phy82328_micro_ctrl_t *micro_ctrl = &(MICRO_CTRL(pc)); 2937 2938 if (!micro_ctrl->enable) { 2939 return; 2940 } 2941 2942 /* Access line side registers */ 2943 saved_side = _phy_82328_intf_side_regs_get(unit, port); 2944 if (saved_side == PHY82328_INTF_SIDE_SYS) { 2945 WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_XPMD_REGS_SEL,PHY82328_INTF_SIDE_LINE); 2946 } 2947 2948 micro_ctrl->count++; 2949 2950 /* Quiet micro */ 2951 data = 0; 2952 mask = 0xff00; 2953 rv = MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REG_0, data, mask); 2954 if (rv != SOC_E_NONE) { 2955 goto fail; 2956 } 2957 sal_udelay(500); 2958 checks = 0; 2959 while (checks < 1000) { 2960 /* Make sure micro really paused */ 2961 rv = READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REG_2, &data); 2962 if (rv != SOC_E_NONE) { 2963 goto fail; 2964 } 2965 if ((data & mask) == 0) { 2966 break; 2967 } 2968 sal_udelay(100); 2969 checks++; 2970 } 2971 if (data & mask) { 2972 rv = READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REG_0, &csr); 2973 if (rv != SOC_E_NONE) { 2974 goto fail; 2975 } 2976 LOG_INFO(BSL_LS_SOC_PHY, 2977 (BSL_META_U(unit, 2978 "82328 microcode did not pause in %s: " 2979 "u=%d p%d 1.ca18/1.ca19=%04x/%04x checks=%d\n"), 2980 loc, unit, port, csr, data, checks)); 2981 } 2982 2983 fail: 2984 if (saved_side != PHY82328_INTF_SIDE_LINE) { 2985 WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_XPMD_REGS_SEL, saved_side); 2986 } 2987 return; 2988 } 2989 2990 STATIC void 2991 _phy_82328_micro_resume(int32 unit, soc_port_t port) 2992 { 2993 phy82328_intf_side_t saved_side; 2994 int32 rv = SOC_E_NONE; 2995 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 2996 phy82328_micro_ctrl_t *micro_ctrl = &(MICRO_CTRL(pc)); 2997 2998 if (!micro_ctrl->enable) { 2999 return; 3000 } 3001 3002 /* Access line side registers */ 3003 saved_side = _phy_82328_intf_side_regs_get(unit, port); 3004 if (saved_side == PHY82328_INTF_SIDE_SYS) { 3005 WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_XPMD_REGS_SEL, PHY82328_INTF_SIDE_LINE); 3006 } 3007 3008 micro_ctrl->count--; 3009 if (micro_ctrl->count <= 0) { 3010 rv = MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REG_0, 3011 0xff00, 0xff00); 3012 if (rv != SOC_E_NONE) { 3013 goto fail; 3014 } 3015 if (micro_ctrl->count < 0) { 3016 LOG_VERBOSE(BSL_LS_SOC_PHY, 3017 (BSL_META_U(unit, 3018 "82328 unmatched micro resume\n"))); 3019 micro_ctrl->count = 0;; 3020 } 3021 } 3022 3023 fail: 3024 if (saved_side != PHY82328_INTF_SIDE_LINE) { 3025 WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_XPMD_REGS_SEL, saved_side); 3026 } 3027 return; 3028 } 3029 3030 /* 3031 * Function: 3032 * phy_82328_an_set 3033 * Purpose: 3034 * Configures auto-negotiation 3035 * Parameters: 3036 * unit - StrataSwitch unit #. 3037 * port - StrataSwitch port #. 3038 * enable - if true, auto-negotiation is enabled. 3039 * Returns: 3040 * SOC_E_XXX 3041 */ 3042 3043 STATIC int32 3044 phy_82328_an_set(int32 unit, soc_port_t port, int32 an) 3045 { 3046 int32 dev_an, dev_an_done; 3047 phy_ctrl_t *pc, *int_pc; 3048 phy82328_intf_cfg_t *line_intf; 3049 3050 pc = EXT_PHY_SW_STATE(unit, port); 3051 int_pc = INT_PHY_SW_STATE(unit, port); 3052 line_intf = &(LINE_INTF(pc)); 3053 3054 LOG_INFO(BSL_LS_SOC_PHY, 3055 (BSL_META_U(unit, 3056 "phy_82328_an_set: u=%d p=%d an=%s\n"), 3057 unit, port, an ? "enable" : "disable")); 3058 3059 /* 3060 * Determining line side AN status 3061 * SR/LR/SR4/LR4/SR2: no AN 3062 * KR/KR4/KR2: line side: cl73/cl72, system side as forced cl72 3063 * CR4/CR: AN enabled in FW, to disable set interface to 40G CR4 DAC(aka XLAUI_DFE), otherwise, CR4 3064 * GMII: AN handled by internal SerDes 3065 */ 3066 switch (line_intf->type) { 3067 case SOC_PORT_IF_GMII: 3068 case SOC_PORT_IF_SGMII: 3069 AN_EN(pc) = an; 3070 SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, an)); 3071 break; 3072 case SOC_PORT_IF_KX: 3073 case SOC_PORT_IF_KR: 3074 case SOC_PORT_IF_KR4: 3075 AN_EN(pc) = 1; 3076 break; 3077 case SOC_PORT_IF_CR4: 3078 AN_EN(pc) = an; 3079 break; 3080 default: 3081 /* Interface does not support AN in the firmware so it's always forced */ 3082 AN_EN(pc) = FALSE; 3083 } 3084 SOC_IF_ERROR_RETURN(_phy_82328_intf_type_set(unit, port, line_intf->type, TRUE)); 3085 3086 /* If not passtrhu an, make sure firmware has enabled an */ 3087 if (line_intf->speed > 1000) { 3088 SOC_IF_ERROR_RETURN(phy_82328_an_get(unit, port, &dev_an, &dev_an_done)); 3089 if (dev_an != AN_EN(pc)) { 3090 LOG_ERROR(BSL_LS_SOC_PHY, 3091 (BSL_META_U(unit, 3092 "82328 device autonegotiation mismatch: u=%d p=%d an=%s\n"), 3093 unit, port, AN_EN(pc) ? "en" : "dis")); 3094 } 3095 } 3096 return SOC_E_NONE; 3097 } 3098 3099 /* 3100 * Function: 3101 * phy_82328_an_get 3102 * Purpose: 3103 * Get the current auto-negotiation status (enabled/busy) 3104 * Parameters: 3105 * unit - StrataSwitch unit #. 3106 * port - StrataSwitch port #. 3107 * an - (OUT) if true, auto-negotiation is enabled. 3108 * an_done - (OUT) if true, auto-negotiation is complete. This 3109 * value is undefined if an == false. 3110 * Returns: 3111 * SOC_E_XXX 3112 */ 3113 3114 STATIC int32 3115 phy_82328_an_get(int32 unit, soc_port_t port, int32 *an, int32 *an_done) 3116 { 3117 uint16 data16 = 0; 3118 phy_ctrl_t *pc, *int_pc; 3119 phy82328_intf_cfg_t *line_intf; 3120 3121 pc = EXT_PHY_SW_STATE(unit, port); 3122 int_pc = INT_PHY_SW_STATE(unit, port); 3123 line_intf = &(LINE_INTF(pc)); 3124 3125 if ((line_intf->type == SOC_PORT_IF_GMII) || (line_intf->type == SOC_PORT_IF_SGMII)) { 3126 SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_GET(int_pc->pd, unit, port, an, an_done)); 3127 } else { 3128 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_AN_REG(unit, pc, 3129 PHY82328_AN_CTRL_REG, &data16)); 3130 *an = ((data16 & PHY82328_AN_ENABLE_MSK) == PHY82328_AN_ENABLE_MSK); 3131 LOG_INFO(BSL_LS_SOC_PHY, 3132 (BSL_META_U(unit, 3133 "PHY82328: AN Enable: 0x%x\n"),data16)); 3134 if (*an) { 3135 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_AN_REG(unit, pc, 3136 PHY82328_AN_STS_REG, &data16)); 3137 3138 LOG_INFO(BSL_LS_SOC_PHY, 3139 (BSL_META_U(unit, 3140 "PHY82328 AN Done: 0x%x\n"),data16)); 3141 *an_done = ((data16 & PHY82328_AN_COMPLETE_MSK) == PHY82328_AN_COMPLETE_MSK); 3142 } 3143 } 3144 3145 return SOC_E_NONE; 3146 } 3147 3148 /* 3149 * Squelch/unsquelch tx in 1.reg.bit 3150 */ 3151 STATIC int32 3152 _phy_82328_tx_squelch_enable(int32 unit, soc_port_t port, phy82328_intf_side_t side, uint8 squelch) 3153 { 3154 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 3155 3156 SOC_IF_ERROR_RETURN( 3157 _phy_82328_modify_pma_pmd_reg (unit, port, pc, 3158 PHY82328_DEV_PMA_PMD, TX_ANATXACONTROL7, 3159 QSFI_TX_ANATXACONTROL7_TX_DISABLE_FORCE_EN_SM_SHIFT, 3160 QSFI_TX_ANATXACONTROL7_TX_DISABLE_FORCE_EN_SM_SHIFT, 1)); 3161 3162 SOC_IF_ERROR_RETURN( 3163 _phy_82328_modify_pma_pmd_reg (unit, port, pc, 3164 PHY82328_DEV_PMA_PMD, TX_ANATXACONTROL7, 3165 QSFI_TX_ANATXACONTROL7_TX_DISABLE_FORCE_VAL_SM_SHIFT, 3166 QSFI_TX_ANATXACONTROL7_TX_DISABLE_FORCE_VAL_SM_SHIFT, squelch? 1:0)); 3167 3168 return SOC_E_NONE; 3169 } 3170 3171 STATIC int32 3172 _phy_82328_tx_squelch(int32 unit, soc_port_t port, phy82328_intf_side_t side, int32 cfg_sql) 3173 { 3174 uint8 squelch = 0; 3175 int32 lane = 0; 3176 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 3177 3178 SOC_IF_ERROR_RETURN( 3179 phy82328_intf_side_reg_select(unit, port, side)); 3180 if (PHY82328_SINGLE_PORT_MODE(pc)) { 3181 for (lane = 0; lane < PHY82328_NUM_LANES; lane++) { 3182 /* Check for all lanes or whether this lane has to be squelched */ 3183 if(cfg_sql & (1<<lane)){ 3184 squelch = 1; 3185 } else { 3186 squelch = 0; 3187 } 3188 LOG_INFO(BSL_LS_SOC_PHY, 3189 (BSL_META_U(unit, 3190 "82328 tx squelch=%d: u=%d p=%d lane=%d\n"), squelch, unit, port, lane)); 3191 3192 /* Select the lane on the line side */ 3193 SOC_IF_ERROR_RETURN(_phy_82328_channel_select (unit, port, side, lane)); 3194 SOC_IF_ERROR_RETURN(_phy_82328_tx_squelch_enable (unit, port, side, squelch)); 3195 } 3196 /* Restore to default single port register access */ 3197 SOC_IF_ERROR_RETURN(_phy_82328_channel_select (unit, port, PHY82328_INTF_SIDE_LINE, PHY82328_ALL_LANES)); 3198 } 3199 else { 3200 squelch = (cfg_sql) ? 1 : 0; 3201 SOC_IF_ERROR_RETURN(_phy_82328_tx_squelch_enable (unit, port, side, squelch)); 3202 LOG_INFO(BSL_LS_SOC_PHY, 3203 (BSL_META_U(unit, 3204 "82328 squelch %s side: u=%d p=%d \n"), 3205 side ? "SYSTEM" : "LINE", unit, port)); 3206 } 3207 3208 if (side != PHY82328_INTF_SIDE_LINE) { 3209 SOC_IF_ERROR_RETURN( 3210 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE)); 3211 } 3212 return SOC_E_NONE; 3213 } 3214 3215 /* 3216 * Function: 3217 * _phy_82328_remote_loopback_get 3218 * Purpose: 3219 * Get 82328 PHY loopback state 3220 * Parameters: 3221 * unit - StrataSwitch unit #. 3222 * port - StrataSwitch port #. 3223 * enable - (OUT) address of location to store binary value for on/off (1/0) 3224 * Returns: 3225 * SOC_E_NONE 3226 */ 3227 STATIC int32 3228 _phy_82328_remote_loopback_get(int32 unit, soc_port_t port, uint32 *enable) 3229 { 3230 uint16 read_data=0,ret_val = 1; 3231 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 3232 3233 /* Remote Loop Back Set <Line Side>*/ 3234 SOC_IF_ERROR_RETURN( 3235 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE)); 3236 3237 /*1 rmt_lpbk_config.rmt_lpbk_en 1.D0E2.0 1*/ 3238 SOC_IF_ERROR_RETURN 3239 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3240 TLB_TX_RMT_LPBK_CONFIG, &read_data)); 3241 3242 read_data &=TLB_TX_RMT_LPBK_CONFIG_RMT_LPBK_EN_MASK; 3243 read_data = read_data >> TLB_TX_RMT_LPBK_CONFIG_RMT_LPBK_EN_SHIFT; 3244 ret_val &=read_data; 3245 3246 /*2 tx_pi_control_5.tx_pi_pass_thru_sel 1.D075.2 0*/ 3247 SOC_IF_ERROR_RETURN 3248 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3249 TX_PI_TX_PI_CONTROL_5, &read_data)); 3250 3251 read_data &=TX_PI_TX_PI_CONTROL_5_TX_PI_PASS_THRU_SEL_MASK; 3252 read_data = read_data >> TX_PI_TX_PI_CONTROL_5_TX_PI_PASS_THRU_SEL_SHIFT; 3253 ret_val &=(!read_data); 3254 3255 /*3 tx_pi_control_0.tx_pi_ext_ctrl_en 1.D070.2 1*/ 3256 SOC_IF_ERROR_RETURN 3257 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3258 TX_PI_TX_PI_CONTROL_0, &read_data)); 3259 read_data &=TX_PI_TX_PI_CONTROL_0_TX_PI_EXT_CTRL_EN_MASK; 3260 read_data = read_data >> TX_PI_TX_PI_CONTROL_0_TX_PI_EXT_CTRL_EN_SHIFT; 3261 ret_val &=read_data; 3262 3263 *enable = ret_val; 3264 return SOC_E_NONE; 3265 } 3266 3267 /* 3268 * Function: 3269 * _phy_82328_remote_loopback_set 3270 * Purpose: 3271 * Get 82328 PHY loopback state 3272 * Parameters: 3273 * unit - StrataSwitch unit #. 3274 * port - StrataSwitch port #. 3275 * enable - address of location to store binary value for on/off (1/0) 3276 * Returns: 3277 * SOC_E_NONE 3278 */ 3279 STATIC int32 3280 _phy_82328_remote_loopback_set(int32 unit,soc_port_t port,int32 enable) 3281 { 3282 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 3283 3284 /* Loopback requires 20-bit datapath */ 3285 if (CUR_DATAPATH(pc) != PHY82328_DATAPATH_20) { 3286 return SOC_E_RESOURCE; 3287 } 3288 3289 /* Remote LoopBk Set <Line Side>*/ 3290 SOC_IF_ERROR_RETURN( 3291 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE)); 3292 SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3293 MGT_TOP_GP_REG_0, 3294 (enable << MGT_TOP_CMN_CTLR_GP_REG_0_DISABLE_TX_SQUELCHING_SHIFT), 3295 MGT_TOP_CMN_CTLR_GP_REG_0_DISABLE_TX_SQUELCHING_MASK)); 3296 3297 if (enable) { 3298 SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3299 TX_ANATXACONTROL7, 0, 3300 QSFI_TX_ANATXACONTROL7_TX_DISABLE_FORCE_VAL_SM_MASK)); 3301 3302 SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3303 TX_ANATXACONTROL7, 0, 3304 QSFI_TX_ANATXACONTROL7_TX_DISABLE_FORCE_EN_SM_MASK)); 3305 3306 /*1 rmt_lpbk_config.rmt_lpbk_en 1.D0E2.0 1*/ 3307 SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3308 TLB_TX_RMT_LPBK_CONFIG, 3309 (1<<TLB_TX_RMT_LPBK_CONFIG_RMT_LPBK_EN_SHIFT), 3310 TLB_TX_RMT_LPBK_CONFIG_RMT_LPBK_EN_MASK)); 3311 /*2 tx_pi_control_5.tx_pi_pass_thru_sel 1.D075.2 0*/ 3312 SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3313 TX_PI_TX_PI_CONTROL_5, 3314 0, 3315 TX_PI_TX_PI_CONTROL_5_TX_PI_PASS_THRU_SEL_MASK)); 3316 sal_udelay(100); 3317 /*3 tx_pi_control_0.tx_pi_ext_ctrl_en 1.D070.2 1*/ 3318 SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3319 TX_PI_TX_PI_CONTROL_0, 3320 (1<<TX_PI_TX_PI_CONTROL_0_TX_PI_EXT_CTRL_EN_SHIFT), 3321 TX_PI_TX_PI_CONTROL_0_TX_PI_EXT_CTRL_EN_MASK)); 3322 SOC_IF_ERROR_RETURN 3323 (_phy_82328_modify_pma_pmd_reg (unit, port, pc, 3324 PHY82328_DEV_PMA_PMD, TX_PI_TX_PI_CONTROL_0, 3325 TX_PI_TX_PI_CONTROL_0_TX_PI_LOOP_TIMING_EN_SHIFT, 3326 TX_PI_TX_PI_CONTROL_0_TX_PI_EN_SHIFT, 0x3)); 3327 } else { 3328 /*1 rmt_lpbk_config.rmt_lpbk_en 1.D0E2.0 1*/ 3329 SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3330 TLB_TX_RMT_LPBK_CONFIG, 3331 0, 3332 TLB_TX_RMT_LPBK_CONFIG_RMT_LPBK_EN_MASK)); 3333 /*2 tx_pi_control_5.tx_pi_pass_thru_sel 1.D075.2 0*/ 3334 SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3335 TX_PI_TX_PI_CONTROL_5, 3336 (1<<TX_PI_TX_PI_CONTROL_5_TX_PI_PASS_THRU_SEL_SHIFT), 3337 TX_PI_TX_PI_CONTROL_5_TX_PI_PASS_THRU_SEL_MASK)); 3338 sal_udelay(100); 3339 /*3 tx_pi_control_0.tx_pi_ext_ctrl_en 1.D070.2 1*/ 3340 SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3341 TX_PI_TX_PI_CONTROL_0, 3342 0, 3343 TX_PI_TX_PI_CONTROL_0_TX_PI_EXT_CTRL_EN_MASK)); 3344 } 3345 return SOC_E_NONE; 3346 } 3347 3348 /* 3349 * Function: 3350 * phy_82328_lb_get 3351 * Purpose: 3352 * Get 82328 PHY loopback state 3353 * Parameters: 3354 * unit - StrataSwitch unit #. 3355 * port - StrataSwitch port #. 3356 * enable - (OUT) address of location to store binary value for on/off (1/0) 3357 * Returns: 3358 * SOC_E_NONE 3359 */ 3360 STATIC int32 3361 phy_82328_lb_get(int32 unit, soc_port_t port, int32 *enable) 3362 { 3363 uint16 read_data=0,ret_val=1; 3364 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 3365 3366 *enable = 0xFFFF; 3367 /* LB Set API Supports System Side*/ 3368 SOC_IF_ERROR_RETURN( 3369 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_SYS)); 3370 3371 /*1 rmt_lpbk_config.rmt_lpbk_en 1.D0E2.0 1*/ 3372 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG (unit, pc, 3373 TLB_TX_RMT_LPBK_CONFIG, &read_data)); 3374 3375 read_data &=TLB_TX_RMT_LPBK_CONFIG_RMT_LPBK_EN_MASK; 3376 read_data = read_data >> TLB_TX_RMT_LPBK_CONFIG_RMT_LPBK_EN_SHIFT; 3377 ret_val &=read_data; 3378 3379 /*2 tx_pi_control_5.tx_pi_pass_thru_sel 1.D075.2 0*/ 3380 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3381 TX_PI_TX_PI_CONTROL_5, &read_data)); 3382 3383 read_data &=TX_PI_TX_PI_CONTROL_5_TX_PI_PASS_THRU_SEL_MASK; 3384 read_data = read_data >> TX_PI_TX_PI_CONTROL_5_TX_PI_PASS_THRU_SEL_SHIFT; 3385 ret_val &=(!read_data); 3386 3387 /*3 tx_pi_control_0.tx_pi_ext_ctrl_en 1.D070.2 1*/ 3388 3389 SOC_IF_ERROR_RETURN (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3390 TX_PI_TX_PI_CONTROL_0, &read_data)); 3391 3392 read_data &=TX_PI_TX_PI_CONTROL_0_TX_PI_EXT_CTRL_EN_MASK; 3393 read_data = read_data >> TX_PI_TX_PI_CONTROL_0_TX_PI_EXT_CTRL_EN_SHIFT; 3394 ret_val &=read_data; 3395 3396 *enable &= ret_val; 3397 3398 SOC_IF_ERROR_RETURN( 3399 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE)); 3400 return SOC_E_NONE; 3401 } 3402 3403 3404 STATIC int32 3405 phy_82328_lb_set(int32 unit, soc_port_t port, int32 enable) 3406 { 3407 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 3408 3409 /* Loopback requires 20-bit datapath */ 3410 if (CUR_DATAPATH(pc) != PHY82328_DATAPATH_20) { 3411 return SOC_E_RESOURCE; 3412 } 3413 /* LB Set API Supports System Side*/ 3414 SOC_IF_ERROR_RETURN( 3415 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_SYS)); 3416 3417 SOC_IF_ERROR_RETURN 3418 (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_XPMD_REGS_SEL, PHY82328_INTF_SIDE_LINE)); 3419 SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3420 MGT_TOP_GP_REG_0, 3421 (enable << MGT_TOP_CMN_CTLR_GP_REG_0_DISABLE_TX_SQUELCHING_SHIFT), 3422 MGT_TOP_CMN_CTLR_GP_REG_0_DISABLE_TX_SQUELCHING_MASK)); 3423 3424 SOC_IF_ERROR_RETURN 3425 (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_XPMD_REGS_SEL, PHY82328_INTF_SIDE_SYS)); 3426 3427 if (enable) { 3428 SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3429 TX_ANATXACONTROL7, 0, 3430 QSFI_TX_ANATXACONTROL7_TX_DISABLE_FORCE_VAL_SM_MASK)); 3431 3432 SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3433 TX_ANATXACONTROL7, 0, 3434 QSFI_TX_ANATXACONTROL7_TX_DISABLE_FORCE_EN_SM_MASK)); 3435 SOC_IF_ERROR_RETURN 3436 (_phy_82328_modify_pma_pmd_reg (unit, port, pc, 3437 PHY82328_DEV_PMA_PMD, TX_PI_TX_PI_CONTROL_0, 3438 TX_PI_TX_PI_CONTROL_0_TX_PI_LOOP_TIMING_EN_SHIFT, 3439 TX_PI_TX_PI_CONTROL_0_TX_PI_EN_SHIFT, 0x3)); 3440 3441 /*1 rmt_lpbk_config.rmt_lpbk_en 1.D0E2.0 1*/ 3442 SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3443 TLB_TX_RMT_LPBK_CONFIG, 3444 (1<<TLB_TX_RMT_LPBK_CONFIG_RMT_LPBK_EN_SHIFT), 3445 TLB_TX_RMT_LPBK_CONFIG_RMT_LPBK_EN_MASK)); 3446 sal_udelay(100); 3447 /*2 tx_pi_control_5.tx_pi_pass_thru_sel 1.D075.2 0*/ 3448 SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3449 TX_PI_TX_PI_CONTROL_5, 3450 0, 3451 TX_PI_TX_PI_CONTROL_5_TX_PI_PASS_THRU_SEL_MASK)); 3452 3453 /*3 tx_pi_control_0.tx_pi_ext_ctrl_en 1.D070.2 1*/ 3454 SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3455 TX_PI_TX_PI_CONTROL_0, 3456 (1<<TX_PI_TX_PI_CONTROL_0_TX_PI_EXT_CTRL_EN_SHIFT), 3457 TX_PI_TX_PI_CONTROL_0_TX_PI_EXT_CTRL_EN_MASK)); 3458 } else { 3459 /*1 rmt_lpbk_config.rmt_lpbk_en 1.D0E2.0 1*/ 3460 SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3461 TLB_TX_RMT_LPBK_CONFIG, 3462 0, 3463 TLB_TX_RMT_LPBK_CONFIG_RMT_LPBK_EN_MASK)); 3464 /*2 tx_pi_control_5.tx_pi_pass_thru_sel 1.D075.2 0*/ 3465 SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3466 TX_PI_TX_PI_CONTROL_5, 3467 (1<<TX_PI_TX_PI_CONTROL_5_TX_PI_PASS_THRU_SEL_SHIFT), 3468 TX_PI_TX_PI_CONTROL_5_TX_PI_PASS_THRU_SEL_MASK)); 3469 sal_udelay(100); 3470 /*3 tx_pi_control_0.tx_pi_ext_ctrl_en 1.D070.2 1*/ 3471 SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3472 TX_PI_TX_PI_CONTROL_0, 3473 0, 3474 TX_PI_TX_PI_CONTROL_0_TX_PI_EXT_CTRL_EN_MASK)); 3475 } 3476 SOC_IF_ERROR_RETURN( 3477 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE)); 3478 return SOC_E_NONE; 3479 } 3480 3481 STATIC int32 3482 _phy_82328_intf_type_set(int32 unit, soc_port_t port, soc_port_if_t pif, int32 must_update) 3483 { 3484 int32 rv = SOC_E_NONE; 3485 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 3486 phy82328_intf_cfg_t *line_intf; 3487 int32 update = 0; 3488 uint16 reg_data = 0, reg_mask = 0; 3489 uint16 data = 0, mask = 0; 3490 3491 line_intf = &(LINE_INTF(pc)); 3492 3493 reg_data = 0; 3494 reg_mask = 0; 3495 3496 if (_phy_82328_intf_is_single_port(pif)) { 3497 if (!PHY82328_SINGLE_PORT_MODE(pc)) { 3498 LOG_ERROR(BSL_LS_SOC_PHY, 3499 (BSL_META_U(unit, 3500 "82328 invalid interface for quad port: u=%d p=%d\n"), 3501 unit, port)); 3502 return SOC_E_CONFIG; 3503 } 3504 /* 3505 * If rx polarity is flipped and the interface is CR4, then change the datapath 3506 * to 20-bit as rx polarity cannot be handle on the line side in 4-bit 3507 */ 3508 if (pif == SOC_PORT_IF_CR4) { 3509 if (AN_EN(pc)) { 3510 if (POL_RX_CFG(pc) && (CUR_DATAPATH(pc) != PHY82328_DATAPATH_20)) { 3511 CUR_DATAPATH(pc) = PHY82328_DATAPATH_20; 3512 update = 1; 3513 } 3514 } else if (CUR_DATAPATH(pc) != CFG_DATAPATH(pc)) { 3515 CUR_DATAPATH(pc) = CFG_DATAPATH(pc); 3516 update = 1; 3517 } 3518 SOC_IF_ERROR_RETURN( 3519 _phy_82328_intf_datapath_reg_get(unit, port, CUR_DATAPATH(pc), &data, &mask)); 3520 reg_data |= data; 3521 reg_mask |= mask; 3522 } 3523 if ((pif != line_intf->type) || must_update) { 3524 update = 1; 3525 } 3526 } else if (_phy_82328_intf_is_quad_port(pif)) { 3527 if (PHY82328_SINGLE_PORT_MODE(pc)) { 3528 LOG_ERROR(BSL_LS_SOC_PHY, 3529 (BSL_META_U(unit, 3530 "82328 invalid interface for single port: u=%d p=%d\n"), 3531 unit, port)); 3532 return SOC_E_CONFIG; 3533 } 3534 3535 if ((line_intf->type != pif) || must_update) { 3536 update = 1; 3537 SOC_IF_ERROR_RETURN( 3538 _phy_82328_intf_type_reg_get(unit, port, pif, PHY82328_INTF_SIDE_LINE, 3539 ®_data, ®_mask)); 3540 } 3541 } else { 3542 LOG_ERROR(BSL_LS_SOC_PHY, 3543 (BSL_META_U(unit, 3544 "82328 invalid interface for port: u=%d p=%d intf=%d\n"), 3545 unit, port, pif)); 3546 return SOC_E_CONFIG; 3547 } 3548 if (update) { 3549 line_intf->type = pif; 3550 SOC_IF_ERROR_RETURN( 3551 _phy_82328_intf_type_reg_get(unit, port, pif, PHY82328_INTF_SIDE_LINE, 3552 &data, &mask)); 3553 reg_data |= data; 3554 reg_mask |= mask; 3555 SOC_IF_ERROR_RETURN(_phy_82328_intf_update(unit, port, reg_data, reg_mask)); 3556 } 3557 return rv; 3558 } 3559 3560 STATIC int32 3561 _phy_82328_intf_line_forced(int32 unit, soc_port_t port, soc_port_if_t intf_type) 3562 { 3563 int32 rv; 3564 switch (intf_type) { 3565 case SOC_PORT_IF_SR: 3566 case SOC_PORT_IF_SR4: 3567 case SOC_PORT_IF_LR: 3568 case SOC_PORT_IF_ZR: 3569 case SOC_PORT_IF_LR4: 3570 case SOC_PORT_IF_XLAUI: 3571 case SOC_PORT_IF_XFI: 3572 case SOC_PORT_IF_SFI: 3573 case SOC_PORT_IF_CR: 3574 rv = TRUE; 3575 break; 3576 default: 3577 rv = FALSE; 3578 } 3579 return rv; 3580 } 3581 3582 /* 3583 * Function: 3584 * phy_82328_interface_set 3585 * Purpose: 3586 * 3587 * 3588 * Parameters: 3589 * unit - StrataSwitch unit #. 3590 * port - StrataSwitch port #. 3591 * pif - one of SOC_PORT_IF_* 3592 * Returns: 3593 * SOC_E_NONE - success 3594 * SOC_E_UNAVAIL - unsupported interface 3595 */ 3596 3597 STATIC int32 3598 phy_82328_interface_set(int32 unit, soc_port_t port, soc_port_if_t pif) 3599 { 3600 int32 rv; 3601 3602 LOG_CLI((BSL_META_U(unit, 3603 "82328 interface set: u=%d p=%d pif=%s\n"), 3604 unit, port, phy82328_intf_names[pif])); 3605 3606 if (pif == SOC_PORT_IF_XGMII) { 3607 return phy_null_interface_set(unit, port, pif); 3608 } 3609 3610 rv = _phy_82328_intf_type_set(unit, port, pif, FALSE); 3611 if (SOC_FAILURE(rv)) { 3612 LOG_INFO(BSL_LS_SOC_PHY, 3613 (BSL_META_U(unit, 3614 "82328 interface set check failed: u=%d p=%d\n"), 3615 unit, port)); 3616 } 3617 if (_phy_82328_intf_line_forced(unit, port, pif)) { 3618 SOC_IF_ERROR_RETURN(phy_82328_an_set(unit, port, 0)); 3619 } 3620 return SOC_E_NONE; 3621 } 3622 3623 /* 3624 * Function: 3625 * phy_82328_interface_get 3626 * Purpose: 3627 * Get the current operating mode of the PHY. 3628 * Parameters: 3629 * unit - StrataSwitch unit #. 3630 * port - StrataSwitch port #. 3631 * pif - (OUT) one of SOC_PORT_IF_* 3632 * Returns: 3633 * SOC_E_NONE 3634 */ 3635 STATIC int32 3636 phy_82328_interface_get(int32 unit, soc_port_t port, soc_port_if_t *pif) 3637 { 3638 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 3639 phy82328_intf_cfg_t *line_intf; 3640 3641 line_intf = &(LINE_INTF(pc)); 3642 *pif = line_intf->type; 3643 3644 return SOC_E_NONE; 3645 } 3646 3647 STATIC int32 3648 _phy_82328_micro_tx_squelch_enable(int32 unit, soc_port_t port, int32 enable) 3649 { 3650 uint16 data; 3651 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 3652 3653 /* 1.ca18[7] 0=micro squelching enabled, 1=micro squelching disabled */ 3654 data = enable ? 0 : 0x80; 3655 SOC_IF_ERROR_RETURN( 3656 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REG_0, data, 0x80)); 3657 return SOC_E_NONE; 3658 } 3659 3660 /* 3661 * Function: 3662 * _phy_82328_control_prbs_enable_set 3663 * Purpose: 3664 * Get the current operating mode of the PHY. 3665 * Parameters: 3666 * unit - StrataSwitch unit #. 3667 * port - StrataSwitch port #. 3668 * enable - PRBS Generator Enable 3669 * Returns: 3670 * SOC_E_NONE 3671 */ 3672 STATIC int32 3673 _phy_82328_control_prbs_enable_set(int32 unit, soc_port_t port, int32 enable) 3674 { 3675 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 3676 3677 /* PRBS requires 20-bit datapath */ 3678 if (CUR_DATAPATH(pc) != PHY82328_DATAPATH_20) { 3679 return SOC_E_RESOURCE; 3680 } 3681 /* Disable Prbs Gen/Chkr First -> Refer Programming Guide 1.2*/ 3682 /* Disable Prbs Gen in TLB_TX_PRBS_GEN_CONFIG 1.D0E1.1 */ 3683 SOC_IF_ERROR_RETURN 3684 3685 (MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3686 TLB_TX_PRBS_GEN_CONFIG, 0, TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_EN_MASK)); 3687 3688 /* Disable Prbs Chkr in in TLB_RX_PRBS_CHK_CONFIG 1.D0D1.0*/ 3689 SOC_IF_ERROR_RETURN 3690 (MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3691 TLB_RX_PRBS_CHK_CONFIG, 0, TLB_RX_PRBS_CHK_CONFIG_PRBS_CHK_EN_MASK)); 3692 3693 if (enable) { 3694 /* Enable Prbs Gen in TLB_TX_PRBS_GEN_CONFIG 1.D0E1.0 */ 3695 /*PRBS Gen Enable*/ 3696 SOC_IF_ERROR_RETURN( 3697 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, TLB_TX_PRBS_GEN_CONFIG, 3698 (1 << TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_EN_SHIFT), 3699 TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_EN_MASK)); 3700 3701 /*Prbs Checker En in TLB_RX_PRBS_CHK_CONFIG 1.D0D1.0*/ 3702 /*PRBS Chk Enable*/ 3703 SOC_IF_ERROR_RETURN ( 3704 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3705 TLB_RX_PRBS_CHK_CONFIG, (1 << TLB_RX_PRBS_CHK_CONFIG_PRBS_CHK_EN_SHIFT), 3706 TLB_RX_PRBS_CHK_CONFIG_PRBS_CHK_EN_MASK)); 3707 } 3708 /* 3709 * If enabling prbs 3710 * disable micro tx squelch updates 3711 * unsquelch tx system 3712 * else 3713 * enable micro tx squelch updates 3714 */ 3715 SOC_IF_ERROR_RETURN(_phy_82328_micro_tx_squelch_enable(unit, port, !enable)); 3716 if (enable) { 3717 SOC_IF_ERROR_RETURN(_phy_82328_tx_squelch(unit, port, PHY82328_INTF_SIDE_SYS, 0)); 3718 } 3719 return SOC_E_NONE; 3720 } 3721 3722 /* 3723 * Function: 3724 * _phy_82328_control_prbs_invert_data_set 3725 * Purpose: 3726 * Get the current operating mode of the PHY. 3727 * Parameters: 3728 * unit - StrataSwitch unit #. 3729 * port - StrataSwitch port #. 3730 * invert - PRBS Invert 3731 * Returns: 3732 * SOC_E_NONE 3733 */ 3734 STATIC int32 3735 _phy_82328_control_prbs_invert_data_set(int32 unit, soc_port_t port, int32 invert) 3736 { 3737 uint16 data; 3738 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 3739 3740 data = invert ? (1 << TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_INV_SHIFT):0; 3741 /*PRBS Gen Invert*/ 3742 SOC_IF_ERROR_RETURN( 3743 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3744 TLB_TX_PRBS_GEN_CONFIG, data, 3745 TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_INV_MASK)); 3746 3747 /*PRBS Chk Invert*/ 3748 SOC_IF_ERROR_RETURN( 3749 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 3750 TLB_RX_PRBS_CHK_CONFIG, data, 3751 TLB_RX_PRBS_CHK_CONFIG_PRBS_CHK_INV_MASK)); 3752 return SOC_E_NONE; 3753 } 3754 3755 /* 3756 * Function: 3757 * _phy_82328_control_prbs_polynomial_set 3758 * Purpose: 3759 * Get the current operating mode of the PHY. 3760 * Parameters: 3761 * unit - StrataSwitch unit #. 3762 * port - StrataSwitch port #. 3763 * polynomial - PRBS Polynomial 3764 * 0==prbs7, 3765 * 1==prbs=15 3766 * 2==prbs=23 3767 * 3==prbs=31 3768 * 3769 * Returns: 3770 * SOC_E_NONE 3771 */ 3772 STATIC int32 3773 _phy_82328_control_prbs_polynomial_set(int32 unit, soc_port_t port, int32 polynomial) 3774 { 3775 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 3776 3777 LOG_INFO(BSL_LS_SOC_PHY, 3778 (BSL_META_U(unit, 3779 "82328 prbs polynomial set: u=%d p=%d polynomial=%d\n"), 3780 unit, port, polynomial)); 3781 switch(polynomial) { 3782 case 0: /* PRBS 7*/ 3783 polynomial = 0; 3784 break; 3785 case 1: /*PRBS15*/ 3786 polynomial = 3; 3787 break; 3788 case 2:/*PRBS23*/ 3789 polynomial = 4; 3790 break; 3791 case 3:/*PRBS31*/ 3792 polynomial = 5; 3793 break; 3794 case 4:/*PRBS 9*/ 3795 polynomial = 1; 3796 break; 3797 case 5:/*PRBS 11*/ 3798 polynomial = 2; 3799 break; 3800 case 6: /*PRBS58*/ 3801 polynomial = 6; 3802 break; 3803 default: 3804 return SOC_E_PARAM; 3805 } 3806 /* Prbs Polynomial in TLB_TX_PRBS_GEN_CONFIG 1.D0E1.[3:1] */ 3807 /*Set Gen Poly*/ 3808 SOC_IF_ERROR_RETURN( 3809 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, TLB_TX_PRBS_GEN_CONFIG, 3810 (polynomial << TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_MODE_SEL_SHIFT), 3811 TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_MODE_SEL_MASK)); 3812 3813 /*Prbs Polynomial in TLB_RX_PRBS_CHK_CONFIG 1.D0D1.[3:1]*/ 3814 /*Set Checker Poly*/ 3815 SOC_IF_ERROR_RETURN( 3816 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, TLB_RX_PRBS_CHK_CONFIG, 3817 (polynomial << TLB_RX_PRBS_CHK_CONFIG_PRBS_CHK_MODE_SEL_SHIFT), 3818 TLB_RX_PRBS_CHK_CONFIG_PRBS_CHK_MODE_SEL_MASK)); 3819 3820 return SOC_E_NONE; 3821 } 3822 3823 3824 int32 phy82328_validate_preemphasis(uint8 pre, uint8 main, uint8 post1, uint8 post2) 3825 { 3826 uint8 post2to1 = (post2==0); 3827 if (pre > 10) { 3828 LOG_ERROR(BSL_LS_SOC_PHY, 3829 (BSL_META("Invalid PRE CURSOR TAP. It should be less than 10\n"))); 3830 return SOC_E_PARAM; 3831 } 3832 if (main > 60) { 3833 LOG_ERROR(BSL_LS_SOC_PHY, 3834 (BSL_META("Invalid MAIN CURSOR TAP. It should be less than 60\n"))); 3835 return SOC_E_PARAM; 3836 } 3837 if ((!post2to1) && (post1 > 18)) { 3838 LOG_ERROR(BSL_LS_SOC_PHY, 3839 (BSL_META("Invalid POST1 CURSOR TAP. It should be less than 18\n"))); 3840 return SOC_E_PARAM; 3841 } 3842 if ((post2to1) && (post1 > 23)) { 3843 LOG_ERROR(BSL_LS_SOC_PHY, 3844 (BSL_META("Invalid POST1 CURSOR TAP. It should be less than 23\n"))); 3845 return SOC_E_PARAM; 3846 } 3847 if (post2 > 5) { 3848 LOG_ERROR(BSL_LS_SOC_PHY, 3849 (BSL_META("Invalid POST2 TAP. It should be less than 5\n"))); 3850 return SOC_E_PARAM; 3851 } 3852 if (main < (pre + post1 + post2 + 1)) { 3853 LOG_ERROR(BSL_LS_SOC_PHY, 3854 (BSL_META("Invalid MAIN TAP. It should be greater than (pre + post1 + post2 + 1)\n"))); 3855 return SOC_E_PARAM; 3856 } 3857 if ((pre + main + post1 + post2) > 60) { 3858 LOG_ERROR(BSL_LS_SOC_PHY, 3859 (BSL_META("Invalid Value. pre + main + post1 + post2 should be less than 60\n"))); 3860 return SOC_E_PARAM; 3861 } 3862 if ((!post2to1) && ((pre + post1) > 22)) { 3863 LOG_ERROR(BSL_LS_SOC_PHY, 3864 (BSL_META("Invalid Value. pre + post1 greater than 22\n"))); 3865 return SOC_E_PARAM; 3866 } 3867 if (post2to1 && ((pre + post1) > 27)) { 3868 LOG_ERROR(BSL_LS_SOC_PHY, 3869 (BSL_META("Invalid Value. pre + post1 greater than 27\n"))); 3870 return SOC_E_PARAM; 3871 } 3872 return SOC_E_NONE; 3873 } 3874 3875 STATIC int32 3876 _phy_82328_control_preemphasis_get(int32 unit, soc_port_t port, soc_phy_control_t type, 3877 phy82328_intf_side_t side, uint32 *value) 3878 { 3879 int32 lane, lane_idx; 3880 uint16 data16 = 0; 3881 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 3882 /* coverity [mixed_enums:FALSE] */ 3883 PHY82328_PREEMPHASIS_LANE_GET(type, lane); 3884 lane_idx = (lane == PHY82328_ALL_LANES) ? 0 : lane; 3885 3886 3887 SOC_IF_ERROR_RETURN( 3888 phy82328_intf_side_reg_select(unit, port, side)); 3889 3890 if (PHY82328_SINGLE_PORT_MODE(pc)) { 3891 SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, side, lane_idx)); 3892 } 3893 /* 3894 * Value format: 3895 * bit 21:18: post2_tap - see 1.d111[10:7] 3896 * bit 16:12: postcursor_tap - see 1.d110[9:5] 3897 * bit 10:05: main_tap - see 1.d111[5:0] 3898 * bit 03:00: precursor_tap - see 1.d110[3:0] 3899 */ 3900 *value = 0; 3901 3902 SOC_IF_ERROR_RETURN( 3903 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_FED_RPTR_TXFIR_CONTROL2, &data16)); 3904 3905 *value = ((data16 & TX_FED_TXFIR_CONTROL2_TXFIR_POST2_MASK) >> 3906 TX_FED_TXFIR_CONTROL2_TXFIR_POST2_SHIFT) << 18; 3907 *value |= ((data16 & TX_FED_TXFIR_CONTROL2_TXFIR_MAIN_OVERRIDE_MASK) << 5); 3908 3909 SOC_IF_ERROR_RETURN( 3910 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_FED_RPTR_TXFIR_CONTROL1, &data16)); 3911 3912 *value |= ((data16 & TX_FED_TXFIR_CONTROL1_TXFIR_POST_OVERRIDE_MASK) >> 3913 TX_FED_TXFIR_CONTROL1_TXFIR_POST_OVERRIDE_SHIFT) << 12; 3914 *value |= (data16 & TX_FED_TXFIR_CONTROL1_TXFIR_PRE_OVERRIDE_MASK); 3915 3916 if (PHY82328_SINGLE_PORT_MODE(pc)) { 3917 SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, side, PHY82328_ALL_LANES)); 3918 } 3919 SOC_IF_ERROR_RETURN( 3920 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE)); 3921 3922 return SOC_E_NONE; 3923 } 3924 3925 STATIC int32 3926 _phy_82328_control_preemphasis_set(int32 unit, soc_port_t port, 3927 soc_phy_control_t type, 3928 phy82328_intf_side_t side, 3929 uint32 value) 3930 { 3931 int32 lane, lane_idx, lane_start, lane_end; 3932 uint8 pre_cursor_tap = 0; 3933 uint8 main_tap = 0; 3934 uint8 post_cursor_tap = 0; 3935 uint8 post2_tap = 0; 3936 3937 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 3938 3939 /* coverity [mixed_enums:FALSE] */ 3940 PHY82328_PREEMPHASIS_LANE_GET(type, lane); 3941 if (!PHY82328_SINGLE_PORT_MODE(pc) && (lane != PHY82328_ALL_LANES)) { 3942 if (lane != (pc->phy_id & 0x03)) { 3943 return SOC_E_PARAM; 3944 } 3945 } 3946 3947 /* 3948 * Value format: 3949 * bit 21:18: post2_tap - see 1.d111[10:7] 3950 * bit 16:12: postcursor_tap - see 1.d110[9:5] 3951 * bit 10:05: main_tap - see 1.d111[5:0] 3952 * bit 03:00: precursor_tap - see 1.d110[3:0] 3953 */ 3954 pre_cursor_tap = (value & 0xf); 3955 main_tap = (value & 0x7E0) >> 5; 3956 post_cursor_tap = (value & 0x1F000) >> 12; 3957 post2_tap = (value & 0x3c0000) >> 18; 3958 3959 SOC_IF_ERROR_RETURN( 3960 phy82328_validate_preemphasis(pre_cursor_tap, main_tap, 3961 post_cursor_tap, post2_tap)); 3962 3963 /* 3964 * Single mode: if lane specified, enable only that lane, otherwise enable all lanes 3965 * Quad mode: if specified lane matches lane for the channel, set the lane 3966 */ 3967 if (PHY82328_SINGLE_PORT_MODE(pc)) { 3968 lane_start = (lane == PHY82328_ALL_LANES) ? 0 : lane; 3969 lane_end = (lane == PHY82328_ALL_LANES) ? PHY82328_NUM_LANES : lane + 1; 3970 } 3971 else { 3972 /* Make sure specified lane matches lane for the channel */ 3973 if (lane != PHY82328_ALL_LANES) { 3974 if (lane != (pc->phy_id & 0x03)) { 3975 return SOC_E_PARAM; 3976 } 3977 } 3978 lane_start = 0; 3979 lane_end = 1; 3980 } 3981 3982 SOC_IF_ERROR_RETURN( 3983 phy82328_intf_side_reg_select(unit, port, side)); 3984 /* Update all requested lanes */ 3985 for (lane_idx = lane_start; lane_idx < lane_end; lane_idx++) { 3986 if (PHY82328_SINGLE_PORT_MODE(pc)) { 3987 /* Select the lane and side to write */ 3988 SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, side, lane_idx)); 3989 } 3990 SOC_IF_ERROR_RETURN( 3991 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, AMS_TX_TX_CTRL_5, 3992 (((post2_tap == 0)?1:0) << AMS_TX_TX_CTRL_5_POST2TO1_SHIFT) , 3993 AMS_TX_TX_CTRL_5_POST2TO1_MASK)); 3994 3995 /* Enable/Disable precursor */ 3996 SOC_IF_ERROR_RETURN( 3997 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, AMS_TX_TX_CTRL_5, 3998 ((pre_cursor_tap?1:0) << AMS_TX_TX_CTRL_5_EN_PRE_SHIFT) , 3999 AMS_TX_TX_CTRL_5_EN_PRE_MASK)); 4000 /* Set precursor */ 4001 SOC_IF_ERROR_RETURN( 4002 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_FED_RPTR_TXFIR_CONTROL1, 4003 pre_cursor_tap , TX_FED_TXFIR_CONTROL1_TXFIR_PRE_OVERRIDE_MASK)); 4004 4005 /* Main tap */ 4006 SOC_IF_ERROR_RETURN( 4007 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_FED_RPTR_TXFIR_CONTROL2, 4008 main_tap, TX_FED_TXFIR_CONTROL2_TXFIR_MAIN_OVERRIDE_MASK)); 4009 4010 /* Enable/Disable postcursor */ 4011 SOC_IF_ERROR_RETURN( 4012 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, AMS_TX_TX_CTRL_5, 4013 ((post_cursor_tap?1:0) << AMS_TX_TX_CTRL_5_EN_POST1_SHIFT) , 4014 AMS_TX_TX_CTRL_5_EN_POST1_MASK)); 4015 4016 /* Set postcursor */ 4017 SOC_IF_ERROR_RETURN( 4018 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_FED_RPTR_TXFIR_CONTROL1, 4019 (post_cursor_tap << TX_FED_TXFIR_CONTROL1_TXFIR_POST_OVERRIDE_SHIFT), 4020 TX_FED_TXFIR_CONTROL1_TXFIR_POST_OVERRIDE_MASK)); 4021 4022 /* Enable/Disable post2cursor */ 4023 SOC_IF_ERROR_RETURN( 4024 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, AMS_TX_TX_CTRL_5, 4025 ((post2_tap?1:0) << AMS_TX_TX_CTRL_5_EN_POST2_SHIFT) , 4026 AMS_TX_TX_CTRL_5_EN_POST2_MASK)); 4027 4028 /* Set post2cursor */ 4029 SOC_IF_ERROR_RETURN( 4030 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_FED_RPTR_TXFIR_CONTROL2, 4031 (post2_tap << TX_FED_TXFIR_CONTROL2_TXFIR_POST2_SHIFT), 4032 TX_FED_TXFIR_CONTROL2_TXFIR_POST2_MASK)); 4033 } 4034 4035 if (PHY82328_SINGLE_PORT_MODE(pc)) { 4036 SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, side, PHY82328_ALL_LANES)); 4037 } 4038 SOC_IF_ERROR_RETURN( 4039 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE)); 4040 return SOC_E_NONE; 4041 } 4042 4043 STATIC int32 4044 _phy_82328_rx_los_control_set(int32 unit, soc_port_t port, uint32 value) 4045 { 4046 phy_ctrl_t *pc= EXT_PHY_SW_STATE(unit, port); 4047 4048 SOC_IF_ERROR_RETURN( 4049 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE)); 4050 4051 SOC_IF_ERROR_RETURN( 4052 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, SIGDET_SIGDET_CTRL_1, 4053 (value?(1<<SIGDET_SIGDET_CTRL_1_SIGNAL_DETECT_FRC_SHIFT):0), 4054 SIGDET_SIGDET_CTRL_1_SIGNAL_DETECT_FRC_MASK)); 4055 FW_RX_LOS(pc) = value; 4056 return SOC_E_NONE; 4057 } 4058 4059 STATIC int32 4060 _phy_82328_do_rxseq_restart(int32 unit, soc_port_t port, phy82328_intf_side_t side) 4061 { 4062 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 4063 PHY_82328_MICRO_PAUSE(unit, port, "rxseq restart1"); 4064 if (side == PHY82328_INTF_SIDE_SYS) { 4065 SOC_IF_ERROR_RETURN( 4066 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_SYS)); 4067 } 4068 SOC_IF_ERROR_RETURN 4069 (MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, XGXS_BLK0_XGXSCONTROL, 4070 0, QSFI_XGXS_BLK0_XGXSCONTROL_START_SEQUENCER_MASK)); 4071 4072 if (side == PHY82328_INTF_SIDE_SYS) { 4073 SOC_IF_ERROR_RETURN( 4074 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE)); 4075 } 4076 PHY_82328_MICRO_RESUME(unit, port); 4077 4078 sal_udelay(800); 4079 4080 PHY_82328_MICRO_PAUSE(unit, port, "rxseq restart 2"); 4081 if (side == PHY82328_INTF_SIDE_SYS) { 4082 SOC_IF_ERROR_RETURN( 4083 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_SYS)); 4084 } 4085 SOC_IF_ERROR_RETURN 4086 (MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4087 XGXS_BLK0_XGXSCONTROL, QSFI_XGXS_BLK0_XGXSCONTROL_START_SEQUENCER_MASK, 4088 QSFI_XGXS_BLK0_XGXSCONTROL_START_SEQUENCER_MASK)); 4089 if (side == PHY82328_INTF_SIDE_SYS) { 4090 SOC_IF_ERROR_RETURN( 4091 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE)); 4092 } 4093 PHY_82328_MICRO_RESUME(unit, port); 4094 4095 return SOC_E_NONE; 4096 } 4097 4098 STATIC int 4099 _phy_82328_mod_auto_detect_set(int unit, soc_port_t port, uint32 value) 4100 { 4101 phy_ctrl_t *pc; 4102 uint16 data; 4103 uint16 rddata; 4104 uint16 count = 0; 4105 uint16 mask; 4106 4107 pc = EXT_PHY_SW_STATE(unit, port); 4108 mask = (MGT_TOP_CMN_CTLR_GP_REG_0_ENABLE_QSFP_MOD_DETECT_MASK | 4109 MGT_TOP_CMN_CTLR_GP_REG_0_ENABLE_SFP_MOD_DETECT_MASK); 4110 data = value ? mask : 0; 4111 4112 SOC_IF_ERROR_RETURN( 4113 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REG_0, data, 4114 mask)); 4115 4116 if (!value) { 4117 /* Request is disabling mod auto detect, need to wait until I2CM FSM becomes IDLE */ 4118 /* Wait approx for 325 ms */ 4119 while (count < PHY82328_I2CM_IDLE_WAIT_COUNT){ 4120 SOC_IF_ERROR_RETURN( 4121 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_I2C_CONTROL_REGISTER, &rddata)); 4122 if ((rddata & 0xC) == 0) { 4123 break; 4124 } 4125 count ++; 4126 sal_usleep(PHY82328_I2CM_IDLE_WAIT_CHUNK * 1000); 4127 } 4128 if (count >= PHY82328_I2CM_IDLE_WAIT_COUNT) { 4129 return SOC_E_BUSY; 4130 } 4131 } 4132 4133 /* Update the global database */ 4134 MOD_AUTO_DETECT(pc) = value ? 1:0; 4135 4136 return SOC_E_NONE; 4137 } 4138 4139 STATIC int 4140 _phy_82328_mod_auto_detect_get(int unit, soc_port_t port, uint32 *value) 4141 { 4142 phy_ctrl_t *pc; 4143 uint16 data; 4144 4145 pc = EXT_PHY_SW_STATE(unit, port); 4146 4147 SOC_IF_ERROR_RETURN( 4148 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REG_0, &data)); 4149 4150 if( data & (MGT_TOP_CMN_CTLR_GP_REG_0_ENABLE_QSFP_MOD_DETECT_MASK | 4151 MGT_TOP_CMN_CTLR_GP_REG_0_ENABLE_SFP_MOD_DETECT_MASK)) { 4152 *value = 1; 4153 } else { 4154 *value = 0; 4155 } 4156 return SOC_E_NONE; 4157 } 4158 4159 /* 4160 * Function: 4161 * _phy_82328_control_set 4162 * Purpose: 4163 * Configure PHY device specific control fucntion. 4164 * Parameters: 4165 * unit - StrataSwitch unit #. 4166 * port - StrataSwitch port #. 4167 * type - Control to update 4168 * value - New setting for the control 4169 * Returns: 4170 * SOC_E_NONE 4171 */ 4172 STATIC int32 4173 _phy_82328_control_set(int32 unit, soc_port_t port, int32 intf, int32 lane, 4174 soc_phy_control_t type, uint32 value) 4175 { 4176 phy_ctrl_t *pc; /* PHY software state */ 4177 int32 rv = SOC_E_UNAVAIL; 4178 4179 pc = EXT_PHY_SW_STATE(unit, port); 4180 4181 PHY_CONTROL_TYPE_CHECK(type); 4182 4183 if (intf == PHY_DIAG_INTF_SYS) { 4184 SOC_IF_ERROR_RETURN( 4185 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_SYS)); 4186 } 4187 4188 switch (type) { 4189 case SOC_PHY_CONTROL_PREEMPHASIS: 4190 /* fall through */ 4191 case SOC_PHY_CONTROL_PREEMPHASIS_LANE0: 4192 /* fall through */ 4193 case SOC_PHY_CONTROL_PREEMPHASIS_LANE1: 4194 /* fall through */ 4195 case SOC_PHY_CONTROL_PREEMPHASIS_LANE2: 4196 /* fall through */ 4197 case SOC_PHY_CONTROL_PREEMPHASIS_LANE3: 4198 rv = _phy_82328_control_preemphasis_set(unit, port, type, 4199 (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? 4200 PHY82328_INTF_SIDE_SYS : PHY82328_INTF_SIDE_LINE, 4201 value); 4202 break; 4203 case SOC_PHY_CONTROL_DRIVER_CURRENT: 4204 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0: 4205 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1: 4206 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2: 4207 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3: 4208 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 4209 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0: 4210 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1: 4211 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2: 4212 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3: 4213 rv = SOC_E_UNAVAIL; 4214 break; 4215 4216 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 4217 rv = _phy_82328_control_prbs_polynomial_set(unit, port, value); 4218 break; 4219 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 4220 rv = _phy_82328_control_prbs_invert_data_set(unit, port, value); 4221 break; 4222 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 4223 /* fall through */ 4224 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 4225 rv = _phy_82328_control_prbs_enable_set(unit, port, value); 4226 break; 4227 case SOC_PHY_CONTROL_LOOPBACK_REMOTE_PCS_BYPASS: 4228 rv = _phy_82328_remote_loopback_set(unit, port, value); 4229 break; 4230 case SOC_PHY_CONTROL_TX_LANE_SQUELCH: 4231 /*Squelch Tx Line Side*/ 4232 rv = _phy_82328_tx_squelch(unit,port,PHY82328_INTF_SIDE_LINE,value); 4233 break; 4234 case SOC_PHY_CONTROL_PORT_PRIMARY: 4235 rv = soc_phyctrl_primary_set(unit, port, (soc_port_t)value); 4236 break; 4237 case SOC_PHY_CONTROL_PORT_OFFSET: 4238 rv = soc_phyctrl_offset_set(unit, port, (int32)value); 4239 break; 4240 case SOC_PHY_CONTROL_RX_POLARITY: 4241 rv = _phy_82328_polarity_flip (unit, port, 4242 PHY82328_POL_DND, (uint16)value); 4243 break; 4244 case SOC_PHY_CONTROL_TX_POLARITY: 4245 rv = _phy_82328_polarity_flip (unit, port, 4246 (uint16)value, PHY82328_POL_DND); 4247 break; 4248 case SOC_PHY_CONTROL_DUMP: 4249 rv = _phy_82328_debug_info(unit, port); 4250 break; 4251 case SOC_PHY_CONTROL_SOFTWARE_RX_LOS: 4252 /* enable/disable RX los on line side*/ 4253 rv = _phy_82328_rx_los_control_set(unit, port, value); 4254 break; 4255 case SOC_PHY_CONTROL_RX_SEQ_TOGGLE: 4256 /* value is not used since this is always a toggle ->1->0 */ 4257 rv = _phy_82328_do_rxseq_restart(unit, port, 4258 (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? 4259 PHY82328_INTF_SIDE_SYS : PHY82328_INTF_SIDE_LINE); 4260 break; 4261 case SOC_PHY_CONTROL_MOD_AUTO_DETECT_ENABLE: 4262 rv = _phy_82328_mod_auto_detect_set(unit, port, value); 4263 break; 4264 4265 case SOC_PHY_CONTROL_LOOPBACK_INTERNAL: 4266 rv = SOC_E_UNAVAIL; 4267 break; 4268 4269 default: 4270 return SOC_E_UNAVAIL; 4271 } 4272 return rv; 4273 } 4274 4275 STATIC int32 4276 phy_82328_control_set(int32 unit, soc_port_t port, 4277 soc_phy_control_t type, uint32 value) 4278 { 4279 SOC_IF_ERROR_RETURN( 4280 _phy_82328_control_set(unit, port, PHY_DIAG_INTF_LINE, 4281 PHY_DIAG_LN_DFLT, type, value)); 4282 return SOC_E_NONE; 4283 } 4284 4285 /* 4286 * Function: 4287 * _phy_82328_control_prbs_enable_get 4288 * Purpose: 4289 * Configure PHY device specific control fucntion. 4290 * Parameters: 4291 * unit - StrataSwitch unit #. 4292 * port - StrataSwitch port #. * 4293 * value - (OUT)Current setting for the PRBS Gen & Chkr 4294 * Returns: 4295 * SOC_E_NONE 4296 */ 4297 STATIC int32 4298 _phy_82328_control_prbs_enable_get(int32 unit, soc_port_t port, uint32 *value) 4299 { 4300 uint16 gen_data=0,chkr_data=0; 4301 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 4302 4303 *value = 0; 4304 /*Prbs Gen in TLB_TX_PRBS_GEN_CONFIG 1.D0E1.0*/ 4305 SOC_IF_ERROR_RETURN( 4306 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4307 TLB_TX_PRBS_GEN_CONFIG, &gen_data)); 4308 gen_data &= TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_EN_MASK; 4309 gen_data = gen_data >> TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_EN_SHIFT; 4310 4311 /*Prbs Checker En in TLB_RX_PRBS_CHK_CONFIG 1.D0D1.0*/ 4312 SOC_IF_ERROR_RETURN( 4313 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4314 TLB_RX_PRBS_CHK_CONFIG, &chkr_data)); 4315 chkr_data &= TLB_RX_PRBS_CHK_CONFIG_PRBS_CHK_EN_MASK; 4316 chkr_data = chkr_data >> TLB_RX_PRBS_CHK_CONFIG_PRBS_CHK_EN_SHIFT; 4317 4318 *value = gen_data && chkr_data; 4319 4320 return SOC_E_NONE; 4321 } 4322 4323 /* 4324 * Function: 4325 * _phy_82328_control_prbs_rx_status_get 4326 * Purpose: 4327 * Configure PHY device specific control fucntion. 4328 * Parameters: 4329 * unit - StrataSwitch unit #. 4330 * port - StrataSwitch port #. * 4331 * value - (OUT)PRBS Status Lock & Error Cntr 4332 * Returns: 4333 * SOC_E_NONE 4334 */ 4335 STATIC int32 4336 _phy_82328_control_prbs_rx_status_get(int32 unit, soc_port_t port, uint16 intf, uint32 *value) 4337 { 4338 uint16 lock = 0, err_lsb = 0, err_msb = 0, lanes = 0, lane_idx = 0; 4339 uint32 err_cnt = 0; 4340 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 4341 4342 if (PHY82328_SINGLE_PORT_MODE(pc)) { 4343 lanes = PHY82328_NUM_LANES; 4344 } 4345 else { 4346 lanes = 1; 4347 } 4348 4349 *value = 0; 4350 for (lane_idx = 0; lane_idx < lanes; lane_idx++) { 4351 if (PHY82328_SINGLE_PORT_MODE(pc)) { 4352 /* Select the lane and side to access */ 4353 SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, 4354 (intf == PHY_DIAG_INTF_LINE) ? PHY82328_INTF_SIDE_LINE 4355 : PHY82328_INTF_SIDE_SYS , lane_idx)); 4356 } 4357 4358 /*Prbs Lock Status in TLB_RX_PRBS_CHK_LOCK_STATUS 1.D0D9.0*/ 4359 SOC_IF_ERROR_RETURN 4360 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4361 TLB_RX_PRBS_CHK_LOCK_STATUS, &lock)); 4362 lock &= TLB_RX_PRBS_CHK_LOCK_STATUS_PRBS_CHK_LOCK_MASK; 4363 4364 /*Prbs Err Cnt MSB in TLB_RX_PRBS_CHK_ERR_CNT_MSB_STATUS 1.D0DA*/ 4365 SOC_IF_ERROR_RETURN( 4366 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4367 TLB_RX_PRBS_CHK_ERR_CNT_MSB_STATUS, &err_msb)); 4368 4369 err_msb &= TLB_RX_PRBS_CHK_ERR_CNT_MSB_STATUS_PRBS_CHK_ERR_CNT_MSB_MASK; 4370 4371 /*Prbs Err Cnt LSB in TLB_RX_PRBS_CHK_ERR_CNT_LSB_STATUS 1.D0DB*/ 4372 SOC_IF_ERROR_RETURN( 4373 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4374 TLB_RX_PRBS_CHK_ERR_CNT_LSB_STATUS, &err_lsb)); 4375 4376 err_cnt = (err_msb << TLB_RX_PRBS_CHK_ERR_CNT_LSB_STATUS_PRBS_CHK_ERR_CNT_LSB_BITS) 4377 |err_lsb; 4378 4379 if (lock && !err_cnt) { /*Locked and No errors*/ 4380 *value |= 0; 4381 } else { 4382 if (!lock) { /*Not Locked*/ 4383 *value |= -1; 4384 } else { 4385 /*Locked With Errors*/ 4386 *value |= err_cnt; 4387 } 4388 } 4389 } 4390 4391 /* Restore to default single port register access */ 4392 if (PHY82328_SINGLE_PORT_MODE(pc)) { 4393 SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, 4394 PHY82328_INTF_SIDE_LINE, PHY82328_ALL_LANES)); 4395 } 4396 4397 return SOC_E_NONE; 4398 } 4399 4400 /* 4401 * Function: 4402 * _phy_82328_control_prbs_tx_invert_data_get 4403 * Purpose: 4404 * Configure PHY device specific control fucntion. 4405 * Parameters: 4406 * unit - StrataSwitch unit #. 4407 * port - StrataSwitch port #. * 4408 * value - (OUT)Current setting for the PRBS Invert 4409 * Returns: 4410 * SOC_E_NONE 4411 */ 4412 STATIC int32 4413 _phy_82328_control_prbs_tx_invert_data_get(int32 unit, soc_port_t port, uint32 *value) 4414 { 4415 uint16 data=0; 4416 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 4417 4418 *value = 0; 4419 /*Prbs Invert in TLB_TX_PRBS_GEN_CONFIG 1.D0E1.4 */ 4420 SOC_IF_ERROR_RETURN 4421 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4422 TLB_TX_PRBS_GEN_CONFIG, &data)); 4423 4424 data &= TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_INV_MASK; 4425 4426 *value = data >> TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_INV_SHIFT; 4427 4428 return SOC_E_NONE; 4429 } 4430 4431 /* 4432 * Function: 4433 * _phy_82328_control_prbs_polynomial_get 4434 * Purpose: 4435 * Configure PHY device specific control fucntion. 4436 * Parameters: 4437 * unit - StrataSwitch unit #. 4438 * port - StrataSwitch port #. * 4439 * value - (OUT)Current setting for the PRBS Polynomial 4440 * 0=prbs7, 4441 * 1=prbs=15 4442 * 2=prbs=23 4443 * 3=prbs=31 4444 * Returns: 4445 * SOC_E_NONE 4446 */ 4447 STATIC int32 4448 _phy_82328_control_prbs_polynomial_get(int32 unit, soc_port_t port, uint32 *value) 4449 { 4450 uint16 data; 4451 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 4452 4453 *value = 0; 4454 /* Prbs Polynomial in TLB_TX_PRBS_GEN_CONFIG 1.D0E1.[3:1] */ 4455 SOC_IF_ERROR_RETURN 4456 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4457 TLB_TX_PRBS_GEN_CONFIG, &data)); 4458 4459 data &= TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_MODE_SEL_MASK; 4460 data = data >> TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_MODE_SEL_SHIFT; 4461 switch(data) { 4462 case 0: /* PRBS 7*/ 4463 *value = 0; 4464 break; 4465 case 3: /*PRBS15*/ 4466 *value = 1; 4467 break; 4468 case 4:/*PRBS23*/ 4469 *value = 2; 4470 break; 4471 case 5:/*PRBS31*/ 4472 *value = 3; 4473 break; 4474 case 1:/*PRBS 9*/ 4475 *value = 4; 4476 break; 4477 case 2:/*PRBS 11*/ 4478 *value = 5; 4479 break; 4480 case 6: /*PRBS58*/ 4481 *value = 6; 4482 break; 4483 } 4484 return SOC_E_NONE; 4485 } 4486 4487 STATIC int32 4488 _phy_82328_debug_info(int32 unit, soc_port_t port) 4489 { 4490 phy_ctrl_t *pc; 4491 phy_ctrl_t *int_pc; 4492 phy82328_intf_cfg_t *intf; 4493 phy82328_intf_cfg_t *line_intf; 4494 phy82328_intf_cfg_t *sys_intf; 4495 phy82328_intf_side_t side, saved_side; 4496 soc_port_if_t iif; 4497 int32 lane, die_temp = 0, i = 0; 4498 int32 ian, ian_done, ilink, ispeed; 4499 uint16 link_sts[PHY82328_NUM_LANES]; 4500 uint16 pol_sts[PHY82328_NUM_LANES]; 4501 uint16 data0, data1, data2, data3, data4; 4502 uint32 primary_port, offset; 4503 uint32 preemphasis[PHY82328_NUM_LANES]; 4504 char *rx_los_sts; 4505 4506 pc = EXT_PHY_SW_STATE(unit, port); 4507 int_pc = INT_PHY_SW_STATE(unit, port); 4508 4509 SOC_IF_ERROR_RETURN(phy_82328_control_get(unit, port, SOC_PHY_CONTROL_PORT_PRIMARY, 4510 &primary_port)); 4511 4512 SOC_IF_ERROR_RETURN(phy_82328_control_get(unit, port, SOC_PHY_CONTROL_PORT_OFFSET, 4513 &offset)); 4514 4515 /* Access line side registers */ 4516 saved_side = _phy_82328_intf_side_regs_get(unit, port); 4517 if (saved_side == PHY82328_INTF_SIDE_SYS) { 4518 SOC_IF_ERROR_RETURN( 4519 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE)); 4520 } 4521 4522 /* firware rev: 1.c161 */ 4523 SOC_IF_ERROR_RETURN 4524 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4525 0xc161, &data0)); 4526 4527 /* micro enabled: 1.ca18 */ 4528 SOC_IF_ERROR_RETURN 4529 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4530 MGT_TOP_GP_REG_0, &data1)); 4531 /* Link sts 1.c0b0*/ 4532 SOC_IF_ERROR_RETURN 4533 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4534 RX_ANARXSTATUS, &data2)); 4535 SOC_IF_ERROR_RETURN 4536 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4537 MGT_TOP_VTMON_STATUS, &data3)); 4538 data3 &= MGT_TOP_CMN_CTLR_VTMON_STATUS_VTMON_DATA_MASK; 4539 rx_los_sts = "NONE"; 4540 die_temp = 425 - ((49935 * data3)/100000); 4541 if ((FW_RX_LOS(pc) & 0x1) == 0x1) { 4542 rx_los_sts = "FW"; 4543 } 4544 4545 LOG_CLI((BSL_META_U(unit, 4546 "Port %-2d: devid=%d, chiprev=%04x, " 4547 "micro ver(1.%04x)=%04x, micro(1.%04x)=%04x, \n" 4548 " pri:offs=%d:%d, mdio=0x%x, datapath=%d, " 4549 "Link (1.%04x)=%04x\n DieTemprature= %d*c," 4550 " Rx LOS=%s\n"), 4551 port, DEVID(pc), DEVREV(pc), XGXS_BLK8_CL73CONTROL8, data0, 4552 MGT_TOP_GP_REG_0, data1, 4553 primary_port, offset, pc->phy_id, 4554 CUR_DATAPATH(pc) == PHY82328_DATAPATH_20 ? 20 : 4, 4555 RX_ANARXSTATUS, data2, die_temp, rx_los_sts)); 4556 LOG_CLI((BSL_META_U(unit, 4557 "AN:%d\n"), AN_EN(pc))); 4558 /* Single PMD control: 1.ca86 */ 4559 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4560 MGT_TOP_SINGLE_PMD_CTRL, &data0)); 4561 4562 /* Broadcast control: 1.c8fe */ 4563 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4564 MGT_TOP_BROADCAST_CTRL, &data1)); 4565 4566 /* Global intf type/speed - driver csr: 1.c841 */ 4567 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4568 MGT_TOP_GP_REGISTER_1, &data2)); 4569 4570 /* Micro csr 1.c843 */ 4571 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4572 MGT_TOP_GP_REGISTER_3, &data3)); 4573 4574 LOG_CLI((BSL_META_U(unit, 4575 " PMD(1.%04x)=%04x, bcctrl(1.%04x)=%04x, \n" 4576 " drvcsr(1.%04x)=%04x, ucsr(1.%04x)=%04x\n"), 4577 MGT_TOP_SINGLE_PMD_CTRL , data0, 4578 MGT_TOP_BROADCAST_CTRL, data1, 4579 MGT_TOP_GP_REGISTER_1, data2, 4580 MGT_TOP_GP_REGISTER_3, data3)); 4581 4582 /* Interfaces: software, hardware, internal serdes */ 4583 line_intf = &(LINE_INTF(pc)); 4584 sys_intf = &(SYS_INTF(pc)); 4585 for (side = PHY82328_INTF_SIDE_LINE; side <= PHY82328_INTF_SIDE_SYS; side++) { 4586 4587 SOC_IF_ERROR_RETURN( 4588 phy82328_intf_side_reg_select(unit, port, side)); 4589 4590 /* control: 1.0000 */ 4591 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4592 IEEE0_BLK_PMA_PMD_PMD_CONTROL_REGISTER, &data1)); 4593 4594 /* PMD type: 1.0007 */ 4595 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4596 IEEE0_BLK_PMA_PMD_PMD_CONTROL_2_REGISTER, &data2)); 4597 4598 /* Loopback 1.d0e2 */ 4599 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4600 TLB_TX_RMT_LPBK_CONFIG, &data3)); 4601 4602 /* Tx disable 1.c08b */ 4603 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_ANATXACONTROL7, 4604 &data4)); 4605 4606 if (PHY82328_SINGLE_PORT_MODE(pc)) { 4607 if (side == PHY82328_INTF_SIDE_SYS) { 4608 PHY_82328_MICRO_PAUSE(unit, port, ""); 4609 } 4610 for (lane = 0; lane < PHY82328_NUM_LANES; lane++) { 4611 SOC_IF_ERROR_RETURN 4612 (_phy_82328_control_preemphasis_get(unit, port, 4613 (SOC_PHY_CONTROL_PREEMPHASIS_LANE0 + lane), side, &preemphasis[lane])); 4614 4615 /* Select the lane and side to write */ 4616 SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, side, lane)); 4617 4618 /* Link: 1.c0b0 */ 4619 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4620 RX_ANARXSTATUS, &(link_sts[lane]))); 4621 4622 if (CUR_DATAPATH(pc) == PHY82328_DATAPATH_20) { 4623 /* Polarity setting: 1.d0e3 */ 4624 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4625 TLB_TX_TLB_TX_MISC_CONFIG, &(pol_sts[lane]))); 4626 } else { 4627 /* Polarity setting: 1.d0a0 */ 4628 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4629 AMS_TX_TX_CTRL_0, &(pol_sts[lane]))); 4630 } 4631 } 4632 /* Back to default channel selection through lane 0 */ 4633 SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, side, PHY82328_ALL_LANES)); 4634 SOC_IF_ERROR_RETURN( 4635 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE)); 4636 if (side == PHY82328_INTF_SIDE_SYS) { 4637 PHY_82328_MICRO_RESUME(unit, port); 4638 } 4639 } else { 4640 SOC_IF_ERROR_RETURN 4641 (_phy_82328_control_preemphasis_get(unit, port, 4642 SOC_PHY_CONTROL_PREEMPHASIS, side, &preemphasis[i])); 4643 4644 /* Link: 1.c0b0 */ 4645 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4646 RX_ANARXSTATUS, &(link_sts[i]))); 4647 if (CUR_DATAPATH(pc) == PHY82328_DATAPATH_20) { 4648 /* Polarity setting: 1.doe3 */ 4649 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4650 TLB_TX_TLB_TX_MISC_CONFIG, 4651 &(pol_sts[i]))); 4652 } else { 4653 /* Polarity setting: 1.d0a0 */ 4654 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 4655 AMS_TX_TX_CTRL_0, 4656 &(pol_sts[i]))); 4657 } 4658 } 4659 intf = (side == PHY82328_INTF_SIDE_LINE) ? line_intf : sys_intf; 4660 if (PHY82328_SINGLE_PORT_MODE(pc)) { 4661 LOG_CLI((BSL_META_U(unit, 4662 " %s: type=%s, speed=%d, " 4663 "forced cl72=%d, mode(1.%04x)=%04x\n" 4664 " pmdtype(1.%04x)=%04x, " 4665 "lb(1.%04x)=%04x, txdis(1.%04x)=%04x\n" 4666 " link(1.%04x) : " 4667 "(ln0=%04x, ln1=%04x, ln2=%04x, ln3=%04x)\n" 4668 " pol(1.%04x) : " 4669 "(ln0=%04x, ln1=%04x, ln2=%04x, ln3=%04x)\n" 4670 " Preemphasis : " 4671 "(ln0=%08x, ln1=%08x, ln2=%08x, ln3=%08x)\n"), 4672 (side == PHY82328_INTF_SIDE_LINE) ? 4673 "Line " : "System ", 4674 phy82328_intf_names[intf->type], intf->speed, 4675 SYS_FORCED_CL72(pc), 4676 IEEE0_BLK_PMA_PMD_PMD_CONTROL_REGISTER, data1, 4677 IEEE0_BLK_PMA_PMD_PMD_CONTROL_2_REGISTER, data2, 4678 TLB_TX_RMT_LPBK_CONFIG, data3, 4679 TX_ANATXACONTROL7, data4, 4680 RX_ANARXSTATUS, link_sts[0], link_sts[1], 4681 link_sts[2], link_sts[3], 4682 CUR_DATAPATH(pc) == PHY82328_DATAPATH_20 ? 4683 TLB_TX_TLB_TX_MISC_CONFIG : AMS_TX_TX_CTRL_0, 4684 pol_sts[0], pol_sts[1], pol_sts[2], pol_sts[3], 4685 preemphasis[0], preemphasis[1], 4686 preemphasis[2], preemphasis[3])); 4687 } else { 4688 LOG_CLI((BSL_META_U(unit, 4689 " %s: type=%s, speed=%d, " 4690 "forced cl72=%d, mode(1.%04x)=%04x\n" 4691 " pmdtype(1.%04x)=%04x, " 4692 "lb(1.%04x)=%04x, txdis(1.%04x)=%04x\n"), 4693 (side == PHY82328_INTF_SIDE_LINE) ? 4694 "Line " : "System ", 4695 phy82328_intf_names[intf->type], 4696 intf->speed, SYS_FORCED_CL72(pc), 4697 IEEE0_BLK_PMA_PMD_PMD_CONTROL_REGISTER, data1, 4698 IEEE0_BLK_PMA_PMD_PMD_CONTROL_2_REGISTER, data2, 4699 TLB_TX_RMT_LPBK_CONFIG, data3, 4700 TX_ANATXACONTROL7, data4)); 4701 4702 LOG_CLI((BSL_META_U(unit, 4703 " Lane %d : link(1.%04x)=%04x," 4704 "pol(1.%04x)=%04x, Preemphasis:%08x"), 4705 i, RX_ANARXSTATUS, link_sts[i], 4706 CUR_DATAPATH(pc) == PHY82328_DATAPATH_20 ? 4707 TLB_TX_TLB_TX_MISC_CONFIG : AMS_TX_TX_CTRL_0, 4708 pol_sts[i], preemphasis[i])); 4709 } 4710 LOG_CLI((BSL_META_U(unit, 4711 "\n"))); 4712 } 4713 SOC_IF_ERROR_RETURN( 4714 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE)); 4715 if (int_pc) { 4716 int32 lb; 4717 SOC_IF_ERROR_RETURN(PHY_INTERFACE_GET(int_pc->pd, unit, port, &iif)); 4718 SOC_IF_ERROR_RETURN(PHY_LINK_GET(int_pc->pd, unit, port, &ilink)); 4719 SOC_IF_ERROR_RETURN(phy_82328_lb_get(unit, port, &lb)); 4720 if (lb) { 4721 /* Clear the sticky bit if in loopback */ 4722 SOC_IF_ERROR_RETURN(PHY_LINK_GET(int_pc->pd, unit, port, &ilink)); 4723 } 4724 SOC_IF_ERROR_RETURN(PHY_SPEED_GET(int_pc->pd, unit, port, &ispeed)); 4725 SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_GET(int_pc->pd, unit, port, &ian, &ian_done)); 4726 LOG_CLI((BSL_META_U(unit, 4727 " Internal: type=%s, speed=%d, link=%d, an=%d\n===\n"), 4728 phy82328_intf_names[iif], ispeed, ilink, ian)); 4729 } 4730 if (saved_side == PHY82328_INTF_SIDE_SYS) { 4731 SOC_IF_ERROR_RETURN( 4732 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_SYS)); 4733 } 4734 4735 return SOC_E_NONE; 4736 } 4737 4738 STATIC int32 4739 _phy_82328_rx_los_control_get(int32 unit, soc_port_t port, uint32 *value) 4740 { 4741 phy_ctrl_t *pc= EXT_PHY_SW_STATE(unit, port); 4742 *value = FW_RX_LOS(pc); 4743 return SOC_E_NONE; 4744 } 4745 4746 /* 4747 * Function: 4748 * phy_82328_control_get 4749 * Purpose: 4750 * Get current control settign of the PHY. 4751 * Parameters: 4752 * unit - StrataSwitch unit #. 4753 * port - StrataSwitch port #. 4754 * type - Control to get 4755 * value - (OUT)Current setting for the control 4756 * Returns: 4757 * SOC_E_NONE 4758 */ 4759 STATIC int32 4760 _phy_82328_control_get(int32 unit, soc_port_t port, int32 intf, int32 lane, 4761 soc_phy_control_t type, uint32 *value) 4762 { 4763 phy_ctrl_t *pc; 4764 soc_port_t offset, primary; 4765 int32 rv = SOC_E_UNAVAIL; 4766 pc = EXT_PHY_SW_STATE(unit, port); 4767 4768 PHY_CONTROL_TYPE_CHECK(type); 4769 4770 if (intf == PHY_DIAG_INTF_SYS) { 4771 SOC_IF_ERROR_RETURN( 4772 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_SYS)); 4773 } 4774 rv = SOC_E_UNAVAIL; 4775 switch(type) { 4776 case SOC_PHY_CONTROL_PREEMPHASIS: 4777 case SOC_PHY_CONTROL_PREEMPHASIS_LANE0: 4778 case SOC_PHY_CONTROL_PREEMPHASIS_LANE1: 4779 case SOC_PHY_CONTROL_PREEMPHASIS_LANE2: 4780 case SOC_PHY_CONTROL_PREEMPHASIS_LANE3: 4781 /* fall through */ 4782 rv = _phy_82328_control_preemphasis_get(unit, port, type, 4783 (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? 4784 PHY82328_INTF_SIDE_SYS : PHY82328_INTF_SIDE_LINE, 4785 value); 4786 break; 4787 case SOC_PHY_CONTROL_DRIVER_CURRENT: 4788 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0: 4789 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1: 4790 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2: 4791 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3: 4792 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 4793 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0: 4794 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1: 4795 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2: 4796 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3: 4797 /* fall through */ 4798 rv = SOC_E_UNAVAIL; 4799 break; 4800 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 4801 rv = _phy_82328_control_prbs_polynomial_get(unit, port, value); 4802 break; 4803 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 4804 rv = _phy_82328_control_prbs_tx_invert_data_get(unit, port, value); 4805 break; 4806 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 4807 /* fall through */ 4808 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 4809 rv = _phy_82328_control_prbs_enable_get(unit, port, value); 4810 break; 4811 case SOC_PHY_CONTROL_PRBS_RX_STATUS: 4812 rv = _phy_82328_control_prbs_rx_status_get(unit, port, intf, value); 4813 break; 4814 case SOC_PHY_CONTROL_LOOPBACK_REMOTE_PCS_BYPASS: 4815 rv = _phy_82328_remote_loopback_get(unit, port, value); 4816 break; 4817 case SOC_PHY_CONTROL_PORT_PRIMARY: 4818 SOC_IF_ERROR_RETURN 4819 (soc_phyctrl_primary_get(unit, port, &primary)); 4820 *value = (uint32) primary; 4821 rv = SOC_E_NONE; 4822 break; 4823 case SOC_PHY_CONTROL_PORT_OFFSET: 4824 SOC_IF_ERROR_RETURN 4825 (soc_phyctrl_offset_get(unit, port, &offset)); 4826 *value = (uint32) offset; 4827 rv = SOC_E_NONE; 4828 break; 4829 case SOC_PHY_CONTROL_RX_SEQ_DONE: 4830 rv = _phy_82328_intf_link_get(unit, port, (int32*)value); 4831 break; 4832 case SOC_PHY_CONTROL_SOFTWARE_RX_LOS: 4833 rv = _phy_82328_rx_los_control_get(unit, port, value); 4834 break; 4835 4836 case SOC_PHY_CONTROL_MOD_AUTO_DETECT_ENABLE: 4837 rv = _phy_82328_mod_auto_detect_get(unit, port, value); 4838 break; 4839 4840 default: 4841 rv = SOC_E_UNAVAIL; 4842 break; 4843 } 4844 4845 return rv; 4846 } 4847 4848 STATIC int32 4849 phy_82328_control_get(int32 unit, soc_port_t port, 4850 soc_phy_control_t type, uint32 *value) 4851 { 4852 SOC_IF_ERROR_RETURN 4853 (_phy_82328_control_get (unit, port, 4854 PHY_DIAG_INTF_LINE, PHY_DIAG_LN_DFLT, type, value)); 4855 4856 return SOC_E_NONE; 4857 } 4858 4859 STATIC int 4860 _phy_82328_bsc_rw(int unit, soc_port_t port, int dev_addr, int opr, 4861 int addr, int count, void *data_array,uint32 ram_start) 4862 { 4863 phy_ctrl_t *pc; 4864 soc_timeout_t to; 4865 uint16 data16; 4866 int i; 4867 int access_type; 4868 int data_type; 4869 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT) 4870 sal_usecs_t start; 4871 sal_usecs_t end; 4872 #endif 4873 4874 if (!data_array) { 4875 return SOC_E_PARAM; 4876 } 4877 4878 if (count > PHY82328_BSC_XFER_MAX) { 4879 return SOC_E_PARAM; 4880 } 4881 4882 pc = EXT_PHY_SW_STATE(unit, port); 4883 data_type = PHY82328_I2C_DATA_TYPE(opr); 4884 access_type = PHY82328_I2C_ACCESS_TYPE(opr); 4885 4886 if (access_type == PHY82328_I2CDEV_WRITE) { 4887 for (i = 0; i < count; i++) { 4888 if (data_type == PHY82328_I2C_8BIT) { 4889 SOC_IF_ERROR_RETURN 4890 (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, ram_start + i, 4891 ((uint8 *)data_array)[i])); 4892 } else { /* 16 bit */ 4893 SOC_IF_ERROR_RETURN 4894 (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, ram_start + i, 4895 ((uint16 *)data_array)[i])); 4896 } 4897 } 4898 } 4899 4900 data16 = ram_start; 4901 SOC_IF_ERROR_RETURN 4902 (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, 0x8004, data16)); 4903 SOC_IF_ERROR_RETURN 4904 (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, 0x8003, addr)); 4905 SOC_IF_ERROR_RETURN 4906 (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, 0x8002, count)); 4907 4908 data16 = 1; 4909 data16 |= (dev_addr<<9); 4910 if (access_type == PHY82328_I2CDEV_WRITE) { 4911 data16 |= PHY82328_WR_FREQ_400KHZ; 4912 } 4913 4914 SOC_IF_ERROR_RETURN 4915 (WRITE_PHY82328_MMF_PMA_PMD_REG(unit,pc,0x8005,data16)); 4916 4917 if (access_type == PHY82328_I2CDEV_WRITE) { 4918 data16 = 0x8000 | PHY82328_BSC_WRITE_OP; 4919 } else { 4920 data16 = 0x8000 | PHY82328_BSC_READ_OP; 4921 } 4922 4923 if (data_type == PHY82328_I2C_16BIT) { 4924 data16 |= (1 << 12); 4925 } 4926 4927 /* Select first i2c port */ 4928 if (PHY82328_SINGLE_PORT_MODE(pc)) { 4929 SOC_IF_ERROR_RETURN 4930 (MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_MISC_CTRL, 4931 0, MGT_TOP_CMN_CTLR_MISC_CTRL_I2C_PORT_SEL_MASK)); 4932 } else { 4933 SOC_IF_ERROR_RETURN 4934 (MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_MISC_CTRL, 4935 (pc->phy_id & 0x3), MGT_TOP_CMN_CTLR_MISC_CTRL_I2C_PORT_SEL_MASK)); 4936 } 4937 4938 SOC_IF_ERROR_RETURN 4939 (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, 0x8000, data16)); 4940 4941 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT) 4942 start = sal_time_usecs(); 4943 #endif 4944 soc_timeout_init(&to, 1000000, 0); 4945 while (!soc_timeout_check(&to)) { 4946 SOC_IF_ERROR_RETURN 4947 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 0x8000, &data16)); 4948 if (((data16 & PHY82328_2W_STAT) == PHY82328_2W_STAT_COMPLETE)) { 4949 break; 4950 } 4951 } 4952 4953 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT) 4954 end = sal_time_usecs(); 4955 #endif 4956 /* need some delays */ 4957 sal_usleep(10000); 4958 4959 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT) 4960 LOG_INFO(BSL_LS_SOC_PHY, 4961 (BSL_META_U(unit, 4962 "BSC command status %d time=%d\n"), 4963 (data16 & PHY82328_2W_STAT), SAL_USECS_SUB(end, start))); 4964 #endif 4965 4966 if (access_type == PHY82328_I2CDEV_WRITE) { 4967 return SOC_E_NONE; 4968 } 4969 4970 if ((data16 & PHY82328_2W_STAT) == PHY82328_2W_STAT_COMPLETE) { 4971 for (i = 0; i < count; i++) { 4972 SOC_IF_ERROR_RETURN 4973 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, (ram_start+i), &data16)); 4974 if (data_type == PHY82328_I2C_16BIT) { 4975 ((uint16 *)data_array)[i] = data16; 4976 LOG_INFO(BSL_LS_SOC_PHY, 4977 (BSL_META_U(unit, 4978 "%04x "), data16)); 4979 } else { 4980 ((uint8 *)data_array)[i] = (uint8)data16; 4981 LOG_INFO(BSL_LS_SOC_PHY, 4982 (BSL_META_U(unit, 4983 "%02x "), data16)); 4984 } 4985 } 4986 } 4987 return SOC_E_NONE; 4988 } 4989 4990 /* 4991 * Read a slave device such as NVRAM/EEPROM connected to the 82328's I2C 4992 * interface. This function will be mainly used for diagnostic or workaround 4993 * purpose. 4994 * Note: 4995 * The size of read_array buffer must be greater than or equal to the 4996 * parameter nbytes. 4997 * usage example: 4998 * Retrieve the first 100 byte data of the non-volatile storage device with 4999 * I2C bus device address 0x50(default SPF eeprom I2C address) on unit 0, 5000 * port 2. 5001 * uint8 data8[100]; 5002 * phy_82328_i2cdev_read(0,2,0x50,0,100,data8); 5003 */ 5004 int 5005 phy_82328_i2cdev_read(int unit, 5006 soc_port_t port, 5007 int dev_addr, /* 7 bit I2C bus device address */ 5008 int offset, /* starting data address to read */ 5009 int nbytes, /* number of bytes to read */ 5010 uint8 *read_array) /* buffer to hold retrieved data */ 5011 { 5012 return _phy_82328_bsc_rw(unit, port, dev_addr, PHY82328_I2CDEV_READ, 5013 offset, nbytes, (void *)read_array, PHY82328_READ_START_ADDR); 5014 5015 } 5016 5017 /* 5018 * Write to a slave device such as NVRAM/EEPROM connected to the 82328's I2C 5019 * interface. This function will be mainly used for diagnostic or workaround 5020 * purpose. 5021 * Note: 5022 * The size of write_array buffer should be equal to the parameter nbytes. 5023 * The EEPROM may limit the maximun write size to 16 bytes 5024 * usage example: 5025 * Write to first 100 byte space of the non-volatile storage device with 5026 * I2C bus device address 0x50(default SPF eeprom I2C address) on unit 0, 5027 * port 2, with written data specified in array data8. 5028 * uint8 data8[100]; 5029 * *** initialize the data8 array with written data *** 5030 * 5031 * phy_82328_i2cdev_write(0,2,0x50,0,100,data8); 5032 */ 5033 5034 int 5035 phy_82328_i2cdev_write(int unit, 5036 soc_port_t port, 5037 int dev_addr, /* I2C bus device address */ 5038 int offset, /* starting data address to write to */ 5039 int nbytes, /* number of bytes to write */ 5040 uint8 *write_array) /* buffer to hold written data */ 5041 { 5042 int j; 5043 int rv = SOC_E_NONE; 5044 5045 for (j = 0; j < (nbytes/PHY82328_BSC_WR_MAX); j++) { 5046 rv = _phy_82328_bsc_rw(unit, port, dev_addr,PHY82328_I2CDEV_WRITE, 5047 offset + j * PHY82328_BSC_WR_MAX, PHY82328_BSC_WR_MAX, 5048 (void *)(write_array + j * PHY82328_BSC_WR_MAX), 5049 PHY82328_WRITE_START_ADDR); 5050 if (rv != SOC_E_NONE) { 5051 return rv; 5052 } 5053 sal_usleep(20000); 5054 } 5055 if (nbytes % PHY82328_BSC_WR_MAX) { 5056 rv = _phy_82328_bsc_rw(unit, port, dev_addr,PHY82328_I2CDEV_WRITE, 5057 offset + j * PHY82328_BSC_WR_MAX, (nbytes % PHY82328_BSC_WR_MAX), 5058 (void *)(write_array + j * PHY82328_BSC_WR_MAX), 5059 PHY82328_WRITE_START_ADDR); 5060 } 5061 return rv; 5062 } 5063 5064 /* 5065 * Function: 5066 * phy_82328_reg_read 5067 * Purpose: 5068 * Routine to read PHY register 5069 * Parameters: 5070 * uint - BCM unit number 5071 * port - port number 5072 * flags - Flags which specify the register type 5073 * phy_reg_addr - Encoded register address 5074 * phy_data - (OUT) Value read from PHY register 5075 * Note: 5076 * This register read function is not thread safe. Higher level 5077 * function that calls this function must obtain a per port lock 5078 * to avoid overriding register page mapping between threads. 5079 */ 5080 STATIC int32 5081 phy_82328_reg_read(int32 unit, soc_port_t port, uint32 flags, 5082 uint32 phy_reg_addr, uint32 *phy_data) 5083 { 5084 uint16 data16; 5085 phy_ctrl_t *pc; /* PHY software state */ 5086 int32 rv = SOC_E_NONE; 5087 int32 rd_cnt = 1; 5088 uint16 regdata = 0; 5089 5090 pc = EXT_PHY_SW_STATE(unit, port); 5091 5092 if (flags & SOC_PHY_I2C_DATA8) { 5093 SOC_IF_ERROR_RETURN 5094 (phy_82328_i2cdev_read(unit, port, 5095 SOC_PHY_I2C_DEVAD(phy_reg_addr), 5096 SOC_PHY_I2C_REGAD(phy_reg_addr), 5097 rd_cnt, 5098 (uint8 *)&data16)); 5099 *phy_data = *((uint8 *)&data16); 5100 } else if (flags & SOC_PHY_I2C_DATA16) { 5101 /* This operation is generally targeted to access 16-bit device, 5102 * such as PHY IC inside the SFP. However there is no 16-bit 5103 * scratch register space on the device. Use 1.800e 5104 * for this operation. 5105 */ 5106 SOC_IF_ERROR_RETURN 5107 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, PHY82328_I2C_TEMP_RAM, 5108 ®data)); 5109 5110 rv = _phy_82328_bsc_rw(unit, port, 5111 SOC_PHY_I2C_DEVAD(phy_reg_addr), 5112 PHY82328_I2C_OP_TYPE(PHY82328_I2CDEV_READ, PHY82328_I2C_16BIT), 5113 SOC_PHY_I2C_REGAD(phy_reg_addr), 1, 5114 (void *)&data16, PHY82328_I2C_TEMP_RAM); 5115 5116 *phy_data = data16; 5117 5118 /* restore the ram register value */ 5119 SOC_IF_ERROR_RETURN 5120 (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, PHY82328_I2C_TEMP_RAM, 5121 regdata)); 5122 } else { 5123 SOC_IF_ERROR_RETURN 5124 (READ_PHY_REG(unit, pc, phy_reg_addr, &data16)); 5125 *phy_data = data16; 5126 } 5127 return rv; 5128 } 5129 5130 /* 5131 * Function: 5132 * phy_82328_reg_write 5133 * Purpose: 5134 * Routine to write PHY register 5135 * Parameters: 5136 * uint - BCM unit number 5137 * port - port number 5138 * flags - Flags which specify the register type 5139 * phy_reg_addr - Encoded register address 5140 * phy_data - Value write to PHY register 5141 * Note: 5142 * This register read function is not thread safe. Higher level 5143 * function that calls this function must obtain a per port lock 5144 * to avoid overriding register page mapping between threads. 5145 */ 5146 STATIC int32 5147 phy_82328_reg_write(int32 unit, soc_port_t port, uint32 flags, 5148 uint32 phy_reg_addr, uint32 phy_data) 5149 { 5150 phy_ctrl_t *pc; /* PHY software state */ 5151 int32 rv = SOC_E_NONE; 5152 uint8 data8[4]; 5153 uint16 data16[2]; 5154 uint16 regdata[2]; 5155 int32 wr_cnt = 1; 5156 5157 pc = EXT_PHY_SW_STATE(unit, port); 5158 5159 if (flags & SOC_PHY_I2C_DATA8) { 5160 data8[0] = (uint8)phy_data; 5161 SOC_IF_ERROR_RETURN 5162 (phy_82328_i2cdev_write(unit, port, 5163 SOC_PHY_I2C_DEVAD(phy_reg_addr), 5164 SOC_PHY_I2C_REGAD(phy_reg_addr), 5165 wr_cnt, 5166 data8)); 5167 5168 } else if (flags & SOC_PHY_I2C_DATA16) { 5169 /* This operation is generally targeted to access 16-bit device, 5170 * such as PHY IC inside the SFP. However there is no 16-bit 5171 * scratch register space on the device. Use 1.800e 5172 * for this operation. 5173 */ 5174 /* save the temp ram register */ 5175 SOC_IF_ERROR_RETURN 5176 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, PHY82328_I2C_TEMP_RAM, 5177 ®data[0])); 5178 data16[0] = phy_data; 5179 rv = _phy_82328_bsc_rw(unit, port, 5180 SOC_PHY_I2C_DEVAD(phy_reg_addr), 5181 PHY82328_I2C_OP_TYPE(PHY82328_I2CDEV_WRITE, PHY82328_I2C_16BIT), 5182 SOC_PHY_I2C_REGAD(phy_reg_addr),wr_cnt, 5183 (void *)data16, PHY82328_I2C_TEMP_RAM); 5184 5185 /* restore the ram register value */ 5186 SOC_IF_ERROR_RETURN 5187 (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, PHY82328_I2C_TEMP_RAM, 5188 regdata[0])); 5189 } else { 5190 SOC_IF_ERROR_RETURN 5191 (WRITE_PHY_REG (unit, pc, phy_reg_addr, 5192 (uint16)phy_data)); 5193 } 5194 return rv; 5195 } 5196 5197 /* 5198 * Function: 5199 * phy_82328_probe 5200 * Purpose: 5201 * Complement the generic phy probe routine to identify this phy when its 5202 * phy id0 and id1 is same as some other phy's. 5203 * Parameters: 5204 * unit - StrataSwitch unit #. 5205 * pc - phy ctrl descriptor. 5206 * Returns: 5207 * SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error> 5208 */ 5209 STATIC int32 5210 phy_82328_probe(int32 unit, phy_ctrl_t *pc) 5211 { 5212 uint32 devid; 5213 uint16 chip_rev; 5214 SOC_IF_ERROR_RETURN(_phy_82328_config_devid(pc->unit, pc->port, pc, &devid)); 5215 SOC_IF_ERROR_RETURN( 5216 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 5217 MGT_TOP_CHIP_REV_REGISTER, 5218 &chip_rev)); 5219 if (devid == PHY82328_ID_82328) { 5220 if (chip_rev == PHY82328A0_CHIP_REV) { 5221 LOG_INFO(BSL_LS_SOC_PHY, 5222 (BSL_META_U(unit, 5223 "PHY82328 Dev found"))); 5224 pc->dev_name = dev_name_82328_a0; 5225 } else if (chip_rev == PHY82328B0_CHIP_REV) { 5226 LOG_INFO(BSL_LS_SOC_PHY, 5227 (BSL_META_U(unit, 5228 "PHY82328 B0 Dev found"))); 5229 pc->dev_name = dev_name_82328_b0; 5230 } else if (chip_rev == PHY82328B1_CHIP_REV) { 5231 LOG_INFO(BSL_LS_SOC_PHY, 5232 (BSL_META_U(unit, 5233 "PHY82328 B1 Dev found"))); 5234 pc->dev_name = dev_name_82328_b1; 5235 } 5236 5237 } else if (devid == PHY82328_ID_82328F) { 5238 if (chip_rev == PHY82328A0_CHIP_REV) { 5239 LOG_INFO(BSL_LS_SOC_PHY, 5240 (BSL_META_U(unit, 5241 "PHY82328F A0 Dev found"))); 5242 pc->dev_name = dev_name_82328f_a0; 5243 } else if (chip_rev == PHY82328B0_CHIP_REV) { 5244 LOG_INFO(BSL_LS_SOC_PHY, 5245 (BSL_META_U(unit, 5246 "PHY82328F B0 Dev found"))); 5247 pc->dev_name = dev_name_82328f_b0; 5248 } else if (chip_rev == PHY82328B1_CHIP_REV) { 5249 LOG_INFO(BSL_LS_SOC_PHY, 5250 (BSL_META_U(unit, 5251 "PHY82328F B1 Dev found"))); 5252 pc->dev_name = dev_name_82328f_b1; 5253 } 5254 5255 } else if (devid == PHY82328_ID_82322) { 5256 if (chip_rev == PHY82328B1_CHIP_REV) { 5257 pc->dev_name = dev_name_82322_b1; 5258 } else { 5259 pc->dev_name = dev_name_82322; 5260 } 5261 } else { /* not found */ 5262 LOG_WARN(BSL_LS_SOC_PHY, 5263 (BSL_META_U(unit, 5264 "port %d: BCM82xxx type PHY device detected, please use " 5265 "phy_82<xxx> config variable to select the specific type\n"), 5266 pc->port)); 5267 return SOC_E_NOT_FOUND; 5268 } 5269 pc->size = sizeof(phy82328_dev_desc_t); 5270 return SOC_E_NONE; 5271 } 5272 5273 /* 5274 * Function: 5275 * phy_82328_ability_advert_set 5276 * Purpose: 5277 * Set the current advertisement for auto-negotiation. 5278 * Parameters: 5279 * unit - StrataSwitch unit #. 5280 * port - StrataSwitch port #. 5281 * mode - Port mode mask indicating supported options/speeds. 5282 * Returns: 5283 * SOC_E_XXX 5284 * Notes: 5285 * The advertisement is set only for the ACTIVE medium. 5286 * No synchronization performed at this level. 5287 */ 5288 5289 STATIC int32 5290 phy_82328_ability_advert_set(int32 unit, soc_port_t port, 5291 soc_port_ability_t *ability) 5292 { 5293 uint16 pause; 5294 phy_ctrl_t *pc, *int_pc; 5295 phy82328_intf_cfg_t *line_intf; 5296 5297 LOG_INFO(BSL_LS_SOC_PHY, 5298 (BSL_META_U(unit, 5299 "82328 Ablity advert Set\n"))); 5300 if (ability == NULL) { 5301 return SOC_E_PARAM; 5302 } 5303 pc = EXT_PHY_SW_STATE(unit, port); 5304 5305 line_intf = &(LINE_INTF(pc)); 5306 if ((line_intf->type == SOC_PORT_IF_KX) || (line_intf->type == SOC_PORT_IF_GMII)) { 5307 int_pc = INT_PHY_SW_STATE(unit, port); 5308 if (int_pc) { 5309 SOC_IF_ERROR_RETURN(PHY_ABILITY_ADVERT_SET(int_pc->pd, unit, port, ability)); 5310 } 5311 return SOC_E_NONE; 5312 } 5313 5314 switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) { 5315 case SOC_PA_PAUSE_TX: /*7.0x0010.10 1*/ 5316 pause = (1<<QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT); 5317 break; 5318 case SOC_PA_PAUSE_RX: /*7.0x0010.11:10 1*/ 5319 pause = (1<<(QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT+1)) | 5320 (1<<QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT); 5321 break; 5322 case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX: /*7.0x0010.11 1*/ 5323 pause = (1<<(QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT+1)); 5324 break; 5325 default: 5326 pause = 0; 5327 break; 5328 } 5329 5330 SOC_IF_ERROR_RETURN 5331 (MODIFY_PHY82328_MMF_AN_REG(unit, pc, 5332 IEEE1_AN_BLK_AN_ADVERTISEMENT_1_REGISTER, 5333 pause, QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_MASK)); 5334 LOG_INFO(BSL_LS_SOC_PHY, 5335 (BSL_META_U(unit, 5336 "phy_82328_ability_advert_set: u=%d p=%d speed(FD)=%x pause=0x%x\n"), 5337 unit, port, ability->speed_full_duplex, ability->pause)); 5338 return SOC_E_NONE; 5339 } 5340 5341 /* 5342 * Function: 5343 * phy_82328_ability_advert_get 5344 * Purpose: 5345 * Get the current advertisement for auto-negotiation. 5346 * Parameters: 5347 * unit - StrataSwitch unit #. 5348 * port - StrataSwitch port #. 5349 * mode - (OUT) Port mode mask indicating supported options/speeds. 5350 * Returns: 5351 * SOC_E_XXX 5352 * Notes: 5353 * The advertisement is retrieved for the ACTIVE medium. 5354 * No synchronization performed at this level. 5355 */ 5356 5357 STATIC int32 5358 phy_82328_ability_advert_get(int32 unit, soc_port_t port, 5359 soc_port_ability_t *ability) 5360 { 5361 phy_ctrl_t *pc, *int_pc; 5362 uint16 pause_adv; 5363 phy82328_intf_cfg_t *line_intf; 5364 5365 soc_port_mode_t mode = 0; 5366 if (ability == NULL) { 5367 return SOC_E_PARAM; 5368 } 5369 sal_memset(ability, 0, sizeof(soc_port_ability_t)); 5370 pc = EXT_PHY_SW_STATE(unit, port); 5371 int_pc = INT_PHY_SW_STATE(unit, port); 5372 line_intf = &(LINE_INTF(pc)); 5373 5374 if ((line_intf->type == SOC_PORT_IF_KX) || (line_intf->type == SOC_PORT_IF_GMII)) { 5375 int_pc = INT_PHY_SW_STATE(unit, port); 5376 if (int_pc) { 5377 SOC_IF_ERROR_RETURN(PHY_ABILITY_ADVERT_GET(int_pc->pd, unit, port, ability)); 5378 } 5379 return SOC_E_NONE; 5380 } 5381 5382 if(PHY82328_SINGLE_PORT_MODE(pc)) { 5383 ability->speed_full_duplex = SOC_PA_SPEED_40GB; 5384 } 5385 else { 5386 ability->speed_full_duplex = SOC_PA_SPEED_10GB; 5387 } 5388 5389 SOC_IF_ERROR_RETURN 5390 (READ_PHY82328_MMF_AN_REG 5391 (unit, pc, IEEE1_AN_BLK_AN_ADVERTISEMENT_1_REGISTER, &pause_adv)); 5392 mode = 0; 5393 5394 switch (pause_adv & QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_MASK) { 5395 case (1<<QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT): /*7.0x0010.10 1*/ 5396 mode = SOC_PA_PAUSE_TX; 5397 break; 5398 case (1<<(QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT+1)): /*7.0x0010.11 1*/ 5399 mode = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 5400 break; 5401 case (1<<(QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT+1)) | 5402 (1<<QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT):/*7.0x0010.11:10 1*/ 5403 mode = SOC_PA_PAUSE_RX; 5404 break; 5405 default: 5406 mode = 0; 5407 break; 5408 } 5409 ability->pause = mode; 5410 LOG_INFO(BSL_LS_SOC_PHY, 5411 (BSL_META_U(unit, 5412 "phy_82328_ability_advert_get: u=%d p=%d speed(FD)=0x%x pause=0x%x\n"), 5413 unit, port, ability->speed_full_duplex, ability->pause)); 5414 return SOC_E_NONE; 5415 } 5416 5417 /* 5418 * Function: 5419 * phy_82328_ability_local_get 5420 * Purpose: 5421 * Get the device's complete abilities. 5422 * Parameters: 5423 * unit - StrataSwitch unit #. 5424 * port - StrataSwitch port #. 5425 * ability - return device's abilities. 5426 * Returns: 5427 * SOC_E_XXX 5428 */ 5429 5430 STATIC int32 5431 phy_82328_ability_local_get(int32 unit, soc_port_t port, soc_port_ability_t *ability) 5432 { 5433 uint32 pa_speed = 0; 5434 phy_ctrl_t *pc; 5435 5436 pc = EXT_PHY_SW_STATE(unit, port); 5437 5438 if (ability == NULL) { 5439 return SOC_E_PARAM; 5440 } 5441 sal_memset(ability, 0, sizeof(soc_port_ability_t)); 5442 pa_speed = PHY82328_SINGLE_PORT_MODE(pc) ? (SOC_PA_SPEED_40GB|SOC_PA_SPEED_42GB) : 5443 (SOC_PA_SPEED_10GB | SOC_PA_SPEED_1000MB | SOC_PA_SPEED_100MB | SOC_PA_SPEED_10MB); 5444 ability->speed_full_duplex = pa_speed; 5445 ability->speed_half_duplex = SOC_PA_ABILITY_NONE; 5446 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 5447 ability->interface = SOC_PA_INTF_XGMII; 5448 ability->medium = SOC_PA_MEDIUM_FIBER; 5449 ability->loopback = SOC_PA_LB_PHY; 5450 ability->flags = SOC_PA_AUTONEG; 5451 5452 LOG_INFO(BSL_LS_SOC_PHY, 5453 (BSL_META_U(unit, 5454 "phy_82328_ability_local_get: u=%d p=%d speed=0x%x\n"), 5455 unit, port, ability->speed_full_duplex)); 5456 5457 return SOC_E_NONE; 5458 } 5459 5460 /* 5461 * Function: 5462 * phy_82328_firmware_set 5463 * Purpose: 5464 * program the given firmware into the SPI-ROM 5465 * Parameters: 5466 * unit - StrataSwitch unit #. 5467 * port - StrataSwitch port #. 5468 * offset - offset to the data stream 5469 * array - the given data 5470 * datalen- the data length 5471 * Returns: 5472 * SOC_E_NONE 5473 */ 5474 5475 STATIC int32 5476 phy_82328_firmware_set(int32 unit, int32 port, int32 offset, uint8 *array,int32 datalen) 5477 { 5478 /* overload this function a littl bit if array == NULL 5479 * special handling for init. uCode broadcast. Internal use only 5480 */ 5481 uint16 chip_rev; 5482 phy_ctrl_t *pc = (phy_ctrl_t*)NULL; 5483 pc = EXT_PHY_SW_STATE(unit, port); 5484 chip_rev = DEVREV(pc); 5485 if (array == NULL) { 5486 if(chip_rev == PHY82328B0_CHIP_REV || chip_rev == PHY82328B1_CHIP_REV) { 5487 return _phy_82328_rom_fw_dload (unit, port, offset, 5488 phy82328B0_ucode_bin, phy82328B0_ucode_bin_len); 5489 } else if(chip_rev == PHY82328A0_CHIP_REV) { 5490 return _phy_82328_rom_fw_dload (unit, port, offset, 5491 phy82328_ucode_bin, phy82328_ucode_bin_len); 5492 } else { 5493 return SOC_E_UNAVAIL; 5494 } 5495 } else { 5496 LOG_WARN(BSL_LS_SOC_PHY, 5497 (BSL_META_U(unit, 5498 "u=%d p=%d firmware download method not supported\n"), 5499 unit, port)); 5500 return SOC_E_UNAVAIL; 5501 } 5502 5503 return SOC_E_NONE; 5504 } 5505 5506 int32 phy82328_uc_dsc_rdy_tim_out(int32 unit, phy_ctrl_t *pc, uint16 timeout_ms) 5507 { 5508 uint16 tim_out = 0, rdy = 0; 5509 for (tim_out = 0; tim_out < 100; tim_out ++) { 5510 PHY82328_RD_UC_DSC_RDY_FOR_CMD(unit, pc, rdy); 5511 if (rdy) { 5512 return SOC_E_NONE; 5513 } 5514 sal_udelay(10 * timeout_ms); 5515 } 5516 LOG_CLI((BSL_META_U(unit, 5517 "UC DSC rdy timeout\n"))); 5518 return SOC_E_INTERNAL; 5519 5520 } 5521 int32 phy82328_serdes_pmd_uc_cmd(int32 unit, soc_port_t port, phy_ctrl_t *pc, uint16 cmd, uint8 supp_info, uint16 timeout) 5522 { 5523 5524 /* Poll for uc_dsc_ready_for_cmd = 1 to indicate serdes ready for command */ 5525 SOC_IF_ERROR_RETURN(phy82328_uc_dsc_rdy_tim_out(unit, pc, timeout)); 5526 5527 SOC_IF_ERROR_RETURN( 5528 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_DSC_UC_CTRL, 5529 (supp_info << DSC_A_DSC_UC_CTRL_UC_DSC_SUPP_INFO_SHIFT), DSC_A_DSC_UC_CTRL_UC_DSC_SUPP_INFO_MASK)); 5530 SOC_IF_ERROR_RETURN( 5531 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_DSC_UC_CTRL, 5532 0x0, DSC_A_DSC_UC_CTRL_UC_DSC_ERROR_FOUND_MASK)); 5533 SOC_IF_ERROR_RETURN( 5534 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_DSC_UC_CTRL, 5535 cmd ,DSC_A_DSC_UC_CTRL_UC_DSC_GP_UC_REQ_MASK)); 5536 5537 SOC_IF_ERROR_RETURN( 5538 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_DSC_UC_CTRL, 5539 0x0, DSC_A_DSC_UC_CTRL_UC_DSC_READY_FOR_CMD_MASK)); 5540 5541 /* Poll for uc_dsc_ready_for_cmd = 1 to indicate serdes ready for command */ 5542 SOC_IF_ERROR_RETURN(phy82328_uc_dsc_rdy_tim_out(unit, pc, timeout)); 5543 5544 return SOC_E_NONE; 5545 } 5546 5547 /* Micro RAM Lane Byte Read */ 5548 int32 phy82328_serdes_rdbl_uc_var(int32 unit, soc_port_t port, phy_ctrl_t *pc, uint8 s_info, uint16 *data16) 5549 { 5550 /* Each lane can have a maximum of 208 bytes in Gallardo */ 5551 if (s_info > 207) { 5552 return SOC_E_INTERNAL; 5553 } 5554 *data16 = 0; 5555 5556 /* Use Serdes FW DSC Command Interface for reading RAM */ 5557 SOC_IF_ERROR_RETURN( 5558 phy82328_serdes_pmd_uc_cmd(unit, port, pc, PHY82328_CMD_READ_UC_LANE_BYTE, s_info, 10)); 5559 SOC_IF_ERROR_RETURN 5560 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_DSC_SCRATCH, data16)); 5561 5562 return SOC_E_NONE; 5563 } 5564 5565 int32 phy82328_restore_trnsum_ctrls(int32 unit, phy_ctrl_t *pc) 5566 { 5567 /* DSC_D_TRNSUM_CTL_1 - Trnsum Ctl 1 */ 5568 SOC_IF_ERROR_RETURN( 5569 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 0, DSC_D_TRNSUM_CTL_1_TRNSUM_EN_MASK)); 5570 SOC_IF_ERROR_RETURN( 5571 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 0, DSC_D_TRNSUM_CTL_1_TRNSUM_ERR_SEL_MASK)); 5572 SOC_IF_ERROR_RETURN( 5573 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 0, DSC_D_TRNSUM_CTL_1_TRNSUM_RANDOM_TAPSEL_DISABLE_MASK)); 5574 SOC_IF_ERROR_RETURN( 5575 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 0, DSC_D_TRNSUM_CTL_1_TRNSUM_INV_PATTERN_EN_MASK)); 5576 SOC_IF_ERROR_RETURN( 5577 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 0, DSC_D_TRNSUM_CTL_1_TRNSUM_PATTERN_FULL_CHECK_OFF_MASK)); 5578 SOC_IF_ERROR_RETURN( 5579 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 0, DSC_D_TRNSUM_CTL_1_TRNSUM_GAIN_MASK)); 5580 SOC_IF_ERROR_RETURN( 5581 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 0, DSC_D_TRNSUM_CTL_1_TRNSUM_EYE_CLOSURE_EN_MASK)); 5582 SOC_IF_ERROR_RETURN( 5583 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 0, DSC_D_TRNSUM_CTL_1_CDR_QPHASE_MULT_EN_MASK)); 5584 SOC_IF_ERROR_RETURN( 5585 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 0, DSC_D_TRNSUM_CTL_1_TRNSUM_TAP_RANGE_SEL_MASK)); 5586 5587 /* DSC_D_TRNSUM_CTL_2 - Trnsum Ctl 2 */ 5588 SOC_IF_ERROR_RETURN( 5589 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_2, 0, DSC_D_TRNSUM_CTL_2_TRNSUM_PATTERN_MASK)); 5590 SOC_IF_ERROR_RETURN( 5591 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_2, 0, DSC_D_TRNSUM_CTL_2_TRNSUM_PATTERN_BIT_EN_MASK)); 5592 5593 /* DSC_D_TRNSUM_CTL_3 - Trnsum Ctl 3 */ 5594 SOC_IF_ERROR_RETURN( 5595 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_3, 0, DSC_D_TRNSUM_CTL_3_TRNSUM_TAP_EN_MASK)); 5596 SOC_IF_ERROR_RETURN( 5597 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_3, 0, DSC_D_TRNSUM_CTL_3_TRNSUM_TAP_SIGN_MASK)); 5598 5599 /* DSC_D_TRNSUM_CTL_4 - Trnsum Ctl 4 */ 5600 SOC_IF_ERROR_RETURN( 5601 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_4, 0, DSC_D_TRNSUM_CTL_4_TDR_TRNSUM_EN_MASK)); 5602 SOC_IF_ERROR_RETURN( 5603 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_4, 0, DSC_D_TRNSUM_CTL_4_TDR_CYCLE_BIN_MASK)); 5604 SOC_IF_ERROR_RETURN( 5605 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_4, 0, DSC_D_TRNSUM_CTL_4_TDR_CYCLE_SEL_MASK)); 5606 SOC_IF_ERROR_RETURN( 5607 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_4, 0, DSC_D_TRNSUM_CTL_4_TDR_BIT_SEL_MASK)); 5608 SOC_IF_ERROR_RETURN( 5609 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_4, 0, DSC_D_TRNSUM_CTL_4_TRNSUM_UNSIGNED_FLIP_MASK)); 5610 SOC_IF_ERROR_RETURN( 5611 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_4, 0, DSC_D_TRNSUM_CTL_4_TRNSUM_UNSIGNED_CORR_MASK)); 5612 5613 return SOC_E_NONE; 5614 } 5615 5616 /* Configures trnsum block before calibrating the P1 slicers */ 5617 /* Desired equation is Sum of [ p(n) ] */ 5618 int32 phy82328_cfg_trnsum_for_eyediag(int32 unit, soc_port_t port, uint8 timeout) 5619 { 5620 phy_ctrl_t *pc; 5621 5622 pc = EXT_PHY_SW_STATE(unit, port); 5623 5624 SOC_IF_ERROR_RETURN(phy82328_restore_trnsum_ctrls(unit, pc)); 5625 5626 /* Select d[0] */ 5627 SOC_IF_ERROR_RETURN( 5628 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_3, 5629 (PHY82328_TRNSUM_TAP_0 << DSC_D_TRNSUM_CTL_3_TRNSUM_TAP_EN_SHIFT), DSC_D_TRNSUM_CTL_3_TRNSUM_TAP_EN_MASK)); 5630 5631 /* Delay range 5 to -2 */ 5632 SOC_IF_ERROR_RETURN( 5633 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 5634 (PHY82328_TRNSUM_TAP_5_TO_N2 << DSC_D_TRNSUM_CTL_1_TRNSUM_TAP_RANGE_SEL_SHIFT), DSC_D_TRNSUM_CTL_1_TRNSUM_TAP_RANGE_SEL_MASK)); 5635 5636 /* Select error from only P1 slicer */ 5637 SOC_IF_ERROR_RETURN( 5638 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 5639 (PHY82328_TRNSUM_ERR_SEL_P1 << DSC_D_TRNSUM_CTL_1_TRNSUM_ERR_SEL_SHIFT) , DSC_D_TRNSUM_CTL_1_TRNSUM_ERR_SEL_MASK)); 5640 5641 /* Comparison */ 5642 SOC_IF_ERROR_RETURN( 5643 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_4, 5644 1, DSC_D_TRNSUM_CTL_4_TRNSUM_UNSIGNED_CORR_MASK)); 5645 5646 /* Not equals */ 5647 SOC_IF_ERROR_RETURN( 5648 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_4, 5649 (1 << DSC_D_TRNSUM_CTL_4_TRNSUM_UNSIGNED_FLIP_SHIFT) , DSC_D_TRNSUM_CTL_4_TRNSUM_UNSIGNED_FLIP_MASK)); 5650 5651 /* Enable the trnsum function (posedge clears) */ 5652 SOC_IF_ERROR_RETURN( 5653 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 5654 (1 << DSC_D_TRNSUM_CTL_1_TRNSUM_EN_SHIFT), DSC_D_TRNSUM_CTL_1_TRNSUM_EN_MASK)); 5655 5656 SOC_IF_ERROR_RETURN( 5657 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_B_DSC_SM_CTRL_5, 5658 timeout , DSC_B_DSC_SM_CTRL_5_MEASURE_TIMEOUT_MASK)); 5659 return SOC_E_NONE; 5660 } 5661 5662 5663 STATIC int32 5664 _phy_82328_diag_eyescan_livelink_en(int32 unit, soc_port_t port, int32 en) 5665 { 5666 uint16 is_micro_stopped = 0; 5667 phy_ctrl_t *pc; 5668 5669 pc = EXT_PHY_SW_STATE(unit, port); 5670 PHY82328_STS_IS_MICRO_STOPPED(unit, port, pc, is_micro_stopped); 5671 if (!is_micro_stopped) { 5672 SOC_IF_ERROR_RETURN( 5673 phy82328_serdes_pmd_uc_cmd(unit, port, pc, PHY82328_CMD_UC_CTRL, PHY82328_CMD_UC_CTRL_STOP_GRACEFULLY, 2000)); 5674 } 5675 /* Enable tuning by uC */ 5676 SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_B_DSC_SM_CTRL_0, 5677 (en << DSC_B_DSC_SM_CTRL_0_UC_TUNE_EN_SHIFT), DSC_B_DSC_SM_CTRL_0_UC_TUNE_EN_MASK)); 5678 if (en) { 5679 SOC_IF_ERROR_RETURN(phy82328_cfg_trnsum_for_eyediag(unit, port, 31)); 5680 } else { 5681 SOC_IF_ERROR_RETURN( 5682 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 0, DSC_D_TRNSUM_CTL_1_TRNSUM_EN_MASK)); 5683 SOC_IF_ERROR_RETURN( 5684 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_B_DSC_SM_CTRL_0, 0, DSC_B_DSC_SM_CTRL_0_UC_TRNSUM_EN_MASK)); 5685 5686 if (!is_micro_stopped) { 5687 SOC_IF_ERROR_RETURN( 5688 phy82328_serdes_pmd_uc_cmd(unit, port, pc, PHY82328_CMD_UC_CTRL, PHY82328_CMD_UC_CTRL_RESUME, 2000)); 5689 } 5690 } 5691 5692 return SOC_E_NONE; 5693 } 5694 5695 int32 phy82328_move_clkp1_offset(int32 unit, phy_ctrl_t *pc , int8 delta) 5696 { 5697 uint8 cnt = 0; 5698 5699 /* Select p1 slicer to adjust */ 5700 SOC_IF_ERROR_RETURN( 5701 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_RX_PI_CONTROL, 5702 (2 << DSC_A_RX_PI_CONTROL_PI_SLICERS_EN_SHIFT), DSC_A_RX_PI_CONTROL_PI_SLICERS_EN_MASK)); 5703 5704 /* 1 for positive step */ 5705 SOC_IF_ERROR_RETURN( 5706 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_RX_PI_CONTROL, 5707 ((delta >0) << DSC_A_RX_PI_CONTROL_PI_PHASE_STEP_DIR_SHIFT) , DSC_A_RX_PI_CONTROL_PI_PHASE_STEP_DIR_MASK)); 5708 5709 /* Step set to 1 */ 5710 SOC_IF_ERROR_RETURN( 5711 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_RX_PI_CONTROL, 5712 1, DSC_A_RX_PI_CONTROL_PI_PHASE_STEP_CNT_MASK)); 5713 if (delta < 0) { 5714 delta = -(delta); 5715 } 5716 5717 for (cnt=0; cnt < delta; cnt++) { 5718 /* Increments/Decrements by 1 every strobe */ 5719 SOC_IF_ERROR_RETURN( 5720 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_RX_PI_CONTROL, 5721 (1 << DSC_A_RX_PI_CONTROL_PI_MANUAL_STROBE_SHIFT), DSC_A_RX_PI_CONTROL_PI_MANUAL_STROBE_MASK)); 5722 } 5723 return SOC_E_NONE; 5724 } 5725 5726 STATIC 5727 int32 phy82328_serdes_poll_dsc_state_equals_uc_tune(int32 unit, phy_ctrl_t *pc, uint32 timeout_ms) 5728 { 5729 5730 uint16 loop, data16 = 0; 5731 for (loop = 0; loop < 110; loop++) { 5732 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 5733 DSC_B_DSC_SM_STATUS_DSC_STATE, &data16)); 5734 data16 = (data16 & DSC_B_DSC_SM_STATUS_DSC_STATE_DSC_STATE_MASK) >> DSC_B_DSC_SM_STATUS_DSC_STATE_DSC_STATE_SHIFT; 5735 if (data16 == PHY82328_DSC_STATE_UC_TUNE) { 5736 return (SOC_E_NONE); 5737 } 5738 sal_udelay(10 * timeout_ms); 5739 } 5740 LOG_CLI((BSL_META_U(unit, 5741 "uc Tune State not occured:Timeout:%d\n"),data16)); 5742 return SOC_E_INTERNAL; 5743 } 5744 5745 STATIC int32 5746 _phy_82328_diag_eyescan_livelink_read(int32 unit, soc_port_t port, int32 *err_counter) 5747 { 5748 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 5749 uint16 data1 = 0, data2 = 0; 5750 5751 SOC_IF_ERROR_RETURN ( 5752 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 5753 0, DSC_D_TRNSUM_CTL_1_TRNSUM_EN_MASK)); 5754 5755 SOC_IF_ERROR_RETURN ( 5756 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 5757 (1 << DSC_D_TRNSUM_CTL_1_TRNSUM_EN_SHIFT), DSC_D_TRNSUM_CTL_1_TRNSUM_EN_MASK)); 5758 5759 SOC_IF_ERROR_RETURN ( 5760 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_B_DSC_SM_CTRL_0, 5761 (1 << DSC_B_DSC_SM_CTRL_0_UC_TRNSUM_EN_SHIFT) ,DSC_B_DSC_SM_CTRL_0_UC_TRNSUM_EN_MASK)); 5762 5763 SOC_IF_ERROR_RETURN( 5764 phy82328_serdes_poll_dsc_state_equals_uc_tune(unit, pc, 2000)); 5765 5766 SOC_IF_ERROR_RETURN ( 5767 READ_PHY82328_MMF_PMA_PMD_REG (unit, pc, DSC_D_TRNSUM_STS_5, &data1)); 5768 SOC_IF_ERROR_RETURN ( 5769 READ_PHY82328_MMF_PMA_PMD_REG (unit, pc, DSC_D_TRNSUM_STS_6, &data2)); 5770 data2 &= 0x3ff; 5771 *err_counter = (data1 << 10) | data2; 5772 SOC_IF_ERROR_RETURN( 5773 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_RX_PI_CONTROL, 5774 (1 << DSC_A_RX_PI_CONTROL_PI_MANUAL_STROBE_SHIFT), DSC_A_RX_PI_CONTROL_PI_MANUAL_STROBE_MASK)); 5775 return SOC_E_NONE; 5776 5777 } 5778 5779 STATIC int32 5780 _phy_82328_diag_eyescan_hoffset_set(int32 unit, soc_port_t port, int32 hoffset) 5781 { 5782 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 5783 5784 /* Setup the P1 slicer vertical level */ 5785 /* Configure dfe_vga_write_tapsel to p1_eyediag mode */ 5786 SOC_IF_ERROR_RETURN( 5787 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_C_DFE_VGA_OVERRIDE, 5788 (0xd << DSC_C_DFE_VGA_OVERRIDE_DFE_VGA_WRITE_TAPSEL_SHIFT) , DSC_C_DFE_VGA_OVERRIDE_DFE_VGA_WRITE_TAPSEL_MASK)); 5789 5790 /* dfe_vga_write_val[8:3] are used to drive the analog control port. */ 5791 SOC_IF_ERROR_RETURN( 5792 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_C_DFE_VGA_OVERRIDE, 5793 ((-(hoffset))<< 3), DSC_C_DFE_VGA_OVERRIDE_DFE_VGA_WRITE_VAL_MASK)); 5794 5795 /* Enable f/w to write the tap values */ 5796 SOC_IF_ERROR_RETURN( 5797 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_C_DFE_VGA_OVERRIDE, 5798 (1 << DSC_C_DFE_VGA_OVERRIDE_DFE_VGA_WRITE_EN_SHIFT), DSC_C_DFE_VGA_OVERRIDE_DFE_VGA_WRITE_EN_MASK)); 5799 5800 SOC_IF_ERROR_RETURN(phy82328_move_clkp1_offset(unit, pc, -32)); 5801 SOC_IF_ERROR_RETURN(phy82328_move_clkp1_offset(unit, pc, 1)); 5802 5803 return SOC_E_NONE; 5804 } 5805 5806 STATIC int32 5807 _phy_82328_diag_eyescan(int32 unit, soc_port_t port, uint32 inst) 5808 { 5809 int32 lane; 5810 int32 intf; 5811 phy82328_intf_side_t side; 5812 int32 rv = SOC_E_NONE, hoffset = 0, voffset = 0, err = 0; 5813 int32 limits[7] = {1835008, 183501, 18350, 1835, 184, 18, 2}; 5814 int8 num_limit = 0; 5815 5816 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 5817 intf = PHY_DIAG_INST_INTF(inst); 5818 if (intf == PHY_DIAG_INTF_SYS) { 5819 side = PHY82328_INTF_SIDE_SYS; 5820 SOC_IF_ERROR_RETURN( 5821 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_SYS)); 5822 } else { 5823 side = PHY82328_INTF_SIDE_LINE; 5824 } 5825 lane = PHY_DIAG_INST_LN(inst); 5826 if (PHY82328_SINGLE_PORT_MODE(pc) && (lane != 0)) { 5827 SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, side, lane)); 5828 } 5829 5830 SOC_IF_ERROR_RETURN( 5831 _phy_82328_diag_eyescan_livelink_en(unit, port, 1)); 5832 5833 LOG_CLI((BSL_META_U(unit, 5834 "Fast eyescan under Processing"))); 5835 for (hoffset = 31; hoffset>=-31; hoffset--) { 5836 rv = _phy_82328_diag_eyescan_hoffset_set(unit, port, hoffset); 5837 if (SOC_FAILURE(rv)) { 5838 LOG_ERROR(BSL_LS_SOC_PHY, 5839 (BSL_META_U(unit, 5840 "82328 failed in HOFFSET SET: u=%d p=%d err=%d\n"), 5841 unit, port, rv)); 5842 goto eye_fail; 5843 } 5844 5845 for (voffset=-31; voffset < 32; voffset++) { 5846 rv = _phy_82328_diag_eyescan_livelink_read(unit, port, &err); 5847 if (SOC_FAILURE(rv)) { 5848 LOG_ERROR(BSL_LS_SOC_PHY, 5849 (BSL_META_U(unit, 5850 "82328 failed in Read BER: u=%d p=%d err=%d\n"), 5851 unit, port, rv)); 5852 goto eye_fail; 5853 } 5854 eye_consol_val[hoffset+31][voffset+31] = err; 5855 } 5856 LOG_CLI((BSL_META_U(unit, 5857 "."))); 5858 SOC_IF_ERROR_RETURN(phy82328_move_clkp1_offset(unit, pc, -32)); 5859 } 5860 LOG_CLI((BSL_META_U(unit, 5861 "\n\n"))); 5862 LOG_CLI((BSL_META_U(unit, 5863 "-30 -25 -20 -15 -10 -5 0 5 10 15 20 25 30\n"))); 5864 LOG_CLI((BSL_META_U(unit, 5865 "-|----|----|----|----|----|----|----|----|----|----|----|----|-\n"))); 5866 5867 for (hoffset = 31; hoffset >=-31; hoffset = hoffset - 1) { 5868 for (voffset = -31; voffset < 32; voffset++) { 5869 err = eye_consol_val[hoffset+31][voffset+31]; 5870 for (num_limit = 0; num_limit < 7; num_limit++) { 5871 if (err >= limits[num_limit]) { 5872 LOG_CLI((BSL_META_U(unit, 5873 "%c"), '0' + num_limit + 1)); 5874 break; 5875 } 5876 } 5877 if (num_limit == 7) { 5878 if ((voffset % 5 )== 0 && (hoffset % 5)==0) { 5879 LOG_CLI((BSL_META_U(unit, 5880 "+"))); 5881 } else if ((voffset % 5)!=0 && (hoffset % 5)==0) { 5882 LOG_CLI((BSL_META_U(unit, 5883 "-"))); 5884 } else if ((voffset % 5)==0 && (hoffset % 5)!=0) { 5885 LOG_CLI((BSL_META_U(unit, 5886 ":"))); 5887 } else { 5888 LOG_CLI((BSL_META_U(unit, 5889 " "))); 5890 } 5891 } 5892 } 5893 LOG_CLI((BSL_META_U(unit, 5894 "\n"))); 5895 } 5896 LOG_CLI((BSL_META_U(unit, 5897 "\n-|----|----|----|----|----|----|----|----|----|----|----|----|-\n"))); 5898 LOG_CLI((BSL_META_U(unit, 5899 "-30 -25 -20 -15 -10 -5 0 5 10 15 20 25 30\n"))); 5900 5901 eye_fail: 5902 SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_B_DSC_SM_CTRL_0, 5903 0, DSC_B_DSC_SM_CTRL_0_UC_TUNE_EN_MASK)); 5904 SOC_IF_ERROR_RETURN ( 5905 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 5906 0, DSC_D_TRNSUM_CTL_1_TRNSUM_EN_MASK)); 5907 SOC_IF_ERROR_RETURN ( 5908 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_B_DSC_SM_CTRL_0, 5909 (0 << DSC_B_DSC_SM_CTRL_0_UC_TRNSUM_EN_SHIFT) ,DSC_B_DSC_SM_CTRL_0_UC_TRNSUM_EN_MASK)); 5910 SOC_IF_ERROR_RETURN( 5911 phy82328_serdes_pmd_uc_cmd(unit, port, pc, PHY82328_CMD_UC_CTRL, 5912 PHY82328_CMD_UC_CTRL_RESUME, 2000)); 5913 if (PHY82328_SINGLE_PORT_MODE(pc) && (lane != 0)) { 5914 SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, PHY82328_INTF_SIDE_LINE, 5915 PHY82328_ALL_LANES)); 5916 } 5917 if (intf == PHY_DIAG_INTF_SYS) { 5918 SOC_IF_ERROR_RETURN( 5919 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE)); 5920 } 5921 return rv; 5922 } 5923 5924 /* 5925 * Function: 5926 * _phy_82328_diag_dsc 5927 * Purpose: 5928 * Diag function for DSC . 5929 * Parameters: 5930 * unit - StrataSwitch unit #. 5931 * port - StrataSwitch port #. 5932 * intf - line/system 5933 * lane - lane number 5934 * type - Control to update 5935 * Returns: 5936 * SOC_E_NONE 5937 */ 5938 STATIC int32 5939 _phy_82328_diag_dsc(int32 unit, soc_port_t port, int32 intf, int32 lane) 5940 { 5941 int32 i, lanes; 5942 uint16 data16 = 0; 5943 int16 temp = 0; 5944 uint16 is_micro_stopped = 0; 5945 phy_ctrl_t *pc; 5946 phy82328_intf_side_t side; 5947 phy82328_serdes_lane_state *dsc_cbp; 5948 phy82328_serdes_lane_state dsc_cb[PHY82328_NUM_LANES]; 5949 pc = EXT_PHY_SW_STATE(unit, port); 5950 5951 if (PHY82328_SINGLE_PORT_MODE(pc)) { 5952 lanes = PHY82328_NUM_LANES; 5953 } 5954 else { 5955 lanes = 1; 5956 } 5957 side = (intf == PHY_DIAG_INTF_LINE) ? PHY82328_INTF_SIDE_LINE : 5958 PHY82328_INTF_SIDE_SYS; 5959 sal_memset(dsc_cb, 0, (sizeof(dsc_cb))); 5960 PHY82328_STS_IS_MICRO_STOPPED(unit, port, pc, is_micro_stopped); 5961 if (!is_micro_stopped) { 5962 SOC_IF_ERROR_RETURN( 5963 phy82328_serdes_pmd_uc_cmd(unit, port, pc, PHY82328_CMD_UC_CTRL, PHY82328_CMD_UC_CTRL_STOP_GRACEFULLY, 2000)); 5964 } 5965 5966 SOC_IF_ERROR_RETURN( 5967 phy82328_intf_side_reg_select(unit, port, side)); 5968 for (i = 0; i < lanes; i++) { 5969 if (PHY82328_SINGLE_PORT_MODE(pc)) { 5970 /* Select the lane and side to access */ 5971 SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, side, i)); 5972 } 5973 dsc_cbp = &(dsc_cb[i]); 5974 SOC_IF_ERROR_RETURN 5975 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, CKRST_CTRL_OSR_MODE_STATUS, &data16)); 5976 dsc_cbp->osr_mode = data16 & CKRST_CTRL_OSR_MODE_STATUS_ST_OSR_MODE_MASK; 5977 5978 SOC_IF_ERROR_RETURN 5979 (phy82328_serdes_rdbl_uc_var (unit, port, pc, 0x0, &data16)); 5980 dsc_cbp->ucv_config = (data16 & 0xff) << 8; 5981 SOC_IF_ERROR_RETURN 5982 (phy82328_serdes_rdbl_uc_var (unit, port, pc, 0x1, &data16)); 5983 dsc_cbp->ucv_config |= (data16 & 0xff); 5984 5985 SOC_IF_ERROR_RETURN 5986 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, SIGDET_SIGDET_STATUS_0, &data16)); 5987 dsc_cbp->sig_det = (data16 & SIGDET_SIGDET_STATUS_0_SIGNAL_DETECT_MASK); 5988 5989 SOC_IF_ERROR_RETURN 5990 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, TLB_RX_PMD_RX_LOCK_STATUS, &data16)); 5991 dsc_cbp->rx_lock = (data16 & TLB_RX_PMD_RX_LOCK_STATUS_PMD_RX_LOCK_MASK); 5992 5993 SOC_IF_ERROR_RETURN 5994 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_CDR_STATUS_INTEG_REG, &data16)); 5995 temp = (int16) data16; 5996 temp <<= (15 -15); 5997 temp >>= (15 - 15 + 0); 5998 5999 dsc_cbp->rx_ppm = (temp/84); 6000 6001 SOC_IF_ERROR_RETURN 6002 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_RX_PI_DIFF_BIN, &data16)); 6003 dsc_cbp->clk90 = (data16 & DSC_A_RX_PI_DIFF_BIN_CNT_D_MINUS_M1_MASK); 6004 dsc_cbp->clkp1 = (data16 & DSC_A_RX_PI_DIFF_BIN_CNT_D_MINUS_P1_MASK) 6005 >> DSC_A_RX_PI_DIFF_BIN_CNT_D_MINUS_P1_SHIFT; 6006 6007 /* drop the MSB, the result is actually valid modulo 128 */ 6008 /* Also flip the sign to account for d-m1, versus m1-d */ 6009 dsc_cbp->clk90 = dsc_cbp->clk90 << 1; 6010 dsc_cbp->clk90 = -(dsc_cbp->clk90 >> 1); 6011 dsc_cbp->clkp1 = dsc_cbp->clkp1 << 1; 6012 dsc_cbp->clkp1 = -(dsc_cbp->clkp1 >> 1); 6013 6014 SOC_IF_ERROR_RETURN 6015 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_CDR_CONTROL_0, &data16)); 6016 dsc_cbp->br_pd_en = (data16 & DSC_A_CDR_CONTROL_0_BR_PD_EN_MASK) >> 6017 DSC_A_CDR_CONTROL_0_BR_PD_EN_SHIFT; 6018 6019 SOC_IF_ERROR_RETURN 6020 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_E_DSC_E_PF_CTRL, &data16)); 6021 dsc_cbp->pf_main = (data16 & DSC_E_DSC_E_PF_CTRL_PF_CTRL_MASK); 6022 6023 SOC_IF_ERROR_RETURN 6024 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_E_DSC_E_CTRL, &data16)); 6025 dsc_cbp->pf_hiz = (data16 & DSC_E_DSC_E_CTRL_PF_HIZ_MASK) >> 6026 DSC_E_DSC_E_CTRL_PF_HIZ_SHIFT; 6027 6028 SOC_IF_ERROR_RETURN 6029 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_E_DSC_E_PF2_LOWP_CTRL, &data16)); 6030 dsc_cbp->pf_low = (data16 & DSC_E_DSC_E_PF2_LOWP_CTRL_PF2_LOWP_CTRL_MASK); 6031 6032 SOC_IF_ERROR_RETURN 6033 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_VGA_P1EYEDIAG_STS, &data16)); 6034 dsc_cbp->vga = (data16 & DSC_D_VGA_P1EYEDIAG_STS_VGA_BIN_MASK); 6035 temp = (int16)data16; 6036 PHY82328_CONV_SIGNED_BYTE(temp, 13, 8); 6037 dsc_cbp->p1_lvl_ctrl = -(temp); 6038 6039 SOC_IF_ERROR_RETURN 6040 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_E_DSC_E_DC_OFFSET, &data16)); 6041 temp = (int16)data16; 6042 PHY82328_CONV_SIGNED_BYTE(temp, 6, 0); 6043 dsc_cbp->dc_offset = temp; 6044 6045 SOC_IF_ERROR_RETURN 6046 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, AMS_RX_RX_CTRL_5, &data16)); 6047 dsc_cbp->pf_bst = ((data16 & AMS_RX_RX_CTRL_5_PKBST_MASK) >> AMS_RX_RX_CTRL_5_PKBST_SHIFT); 6048 6049 SOC_IF_ERROR_RETURN 6050 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_DFE_1_STS, &data16)); 6051 6052 dsc_cbp->dfe1 = (((data16 & DSC_D_DFE_1_STS_DFE_1_E_MASK) >> DSC_D_DFE_1_STS_DFE_1_E_SHIFT) + 6053 (data16 & DSC_D_DFE_1_STS_DFE_1_CMN_MASK)); 6054 dsc_cbp->dfe1_dcd = (((data16 & DSC_D_DFE_1_STS_DFE_1_E_MASK) >> DSC_D_DFE_1_STS_DFE_1_E_SHIFT) - 6055 ((data16 & DSC_D_DFE_1_STS_DFE_1_O_MASK) >> DSC_D_DFE_1_STS_DFE_1_O_SHIFT)); 6056 SOC_IF_ERROR_RETURN 6057 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_DFE_2_STS, &data16)); 6058 6059 dsc_cbp->dfe2 = (((data16 & DSC_D_DFE_2_STS_DFE_2_SE_MASK) >> DSC_D_DFE_2_STS_DFE_2_SE_SHIFT) ? 6060 -(((data16 & DSC_D_DFE_2_STS_DFE_2_E_MASK) >> DSC_D_DFE_2_STS_DFE_2_E_SHIFT) + 6061 (data16 & DSC_D_DFE_2_STS_DFE_2_CMN_MASK)) : 6062 (((data16 & DSC_D_DFE_2_STS_DFE_2_E_MASK) >> DSC_D_DFE_2_STS_DFE_2_E_SHIFT) + 6063 (data16 & DSC_D_DFE_2_STS_DFE_2_CMN_MASK))); 6064 6065 6066 dsc_cbp->dfe2_dcd = (((data16 & DSC_D_DFE_2_STS_DFE_2_SE_MASK) >> DSC_D_DFE_2_STS_DFE_2_SE_SHIFT) ? 6067 -((data16 & DSC_D_DFE_2_STS_DFE_2_E_MASK) >> DSC_D_DFE_2_STS_DFE_2_E_SHIFT) : 6068 ((data16 & DSC_D_DFE_2_STS_DFE_2_E_MASK) >> DSC_D_DFE_2_STS_DFE_2_E_SHIFT)) - 6069 (((data16 & DSC_D_DFE_2_STS_DFE_2_SO_MASK) >> DSC_D_DFE_2_STS_DFE_2_SO_SHIFT) ? 6070 -((data16 & DSC_D_DFE_2_STS_DFE_2_O_MASK) >> DSC_D_DFE_2_STS_DFE_2_O_SHIFT) : 6071 ((data16 & DSC_D_DFE_2_STS_DFE_2_O_MASK) >> DSC_D_DFE_2_STS_DFE_2_O_SHIFT)); 6072 6073 SOC_IF_ERROR_RETURN 6074 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_DFE_3_4_5_STS, &data16)); 6075 temp = (int16)data16; 6076 PHY82328_CONV_SIGNED_BYTE(temp, 5, 0); 6077 dsc_cbp->dfe3 = temp; 6078 6079 SOC_IF_ERROR_RETURN 6080 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_DFE_3_4_5_STS, &data16)); 6081 temp = (int16)data16; 6082 PHY82328_CONV_SIGNED_BYTE(temp, 10, 6); 6083 dsc_cbp->dfe4 = temp; 6084 6085 SOC_IF_ERROR_RETURN 6086 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_DFE_3_4_5_STS, &data16)); 6087 temp = (int16)data16; 6088 PHY82328_CONV_SIGNED_BYTE(temp, 15, 11); 6089 dsc_cbp->dfe5 = temp; 6090 6091 SOC_IF_ERROR_RETURN 6092 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_E_DSC_E_OFFSET_ADJ_P1_EVEN, &data16)); 6093 temp = (int16)data16; 6094 PHY82328_CONV_SIGNED_BYTE(temp, 5, 0); 6095 dsc_cbp->pe = (4*temp) - 30; 6096 6097 SOC_IF_ERROR_RETURN 6098 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_E_DSC_E_OFFSET_ADJ_DATA_EVEN, &data16)); 6099 temp = (int16)data16; 6100 PHY82328_CONV_SIGNED_BYTE(temp, 5, 0); 6101 dsc_cbp->ze = (4*temp) - 30; 6102 6103 SOC_IF_ERROR_RETURN 6104 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_E_DSC_E_OFFSET_ADJ_M1_EVEN, &data16)); 6105 temp = (int16)data16; 6106 PHY82328_CONV_SIGNED_BYTE(temp, 5, 0); 6107 dsc_cbp->me = (4*temp) - 30; 6108 6109 SOC_IF_ERROR_RETURN 6110 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_E_DSC_E_OFFSET_ADJ_P1_ODD, &data16)); 6111 temp = (int16)data16; 6112 PHY82328_CONV_SIGNED_BYTE(temp, 5, 0); 6113 dsc_cbp->po = (4*temp) - 30; 6114 6115 SOC_IF_ERROR_RETURN 6116 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_E_DSC_E_OFFSET_ADJ_DATA_ODD, &data16)); 6117 temp = (int16)data16; 6118 PHY82328_CONV_SIGNED_BYTE(temp, 5, 0); 6119 dsc_cbp->zo = (4*temp) - 30; 6120 6121 SOC_IF_ERROR_RETURN 6122 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_E_DSC_E_OFFSET_ADJ_M1_ODD, &data16)); 6123 temp = (int16)data16; 6124 PHY82328_CONV_SIGNED_BYTE(temp, 5, 0); 6125 dsc_cbp->mo = (4*temp) - 30; 6126 6127 SOC_IF_ERROR_RETURN 6128 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_PI_TX_PI_STATUS_1, &data16)); 6129 dsc_cbp->tx_ppm = data16/21; 6130 6131 SOC_IF_ERROR_RETURN 6132 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_FED_RPTR_TXFIR_STATUS1, &data16)); 6133 dsc_cbp->txfir_pre = data16 & TX_FED_TXFIR_STATUS1_TXFIR_PRE_AFTER_OVR_MASK; 6134 6135 SOC_IF_ERROR_RETURN 6136 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_FED_RPTR_TXFIR_STATUS2, &data16)); 6137 dsc_cbp->txfir_main = data16 & TX_FED_TXFIR_STATUS2_TXFIR_MAIN_AFTER_OVR_MASK; 6138 6139 SOC_IF_ERROR_RETURN 6140 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_FED_RPTR_TXFIR_STATUS1, &data16)); 6141 dsc_cbp->txfir_post1 = (data16 & TX_FED_TXFIR_STATUS1_TXFIR_POST_AFTER_OVR_MASK) >> 6142 TX_FED_TXFIR_STATUS1_TXFIR_POST_AFTER_OVR_SHIFT; 6143 6144 SOC_IF_ERROR_RETURN 6145 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_FED_RPTR_TXFIR_STATUS1, &data16)); 6146 dsc_cbp->txfir_post2 = (data16 & TX_FED_TXFIR_CONTROL2_TXFIR_POST2_MASK) >> 6147 TX_FED_TXFIR_CONTROL2_TXFIR_POST2_SHIFT; 6148 6149 SOC_IF_ERROR_RETURN 6150 (phy82328_serdes_rdbl_uc_var(unit, port, pc, 0xd, &data16)); 6151 dsc_cbp->heye_left = data16; 6152 6153 SOC_IF_ERROR_RETURN 6154 (phy82328_serdes_rdbl_uc_var(unit, port, pc, 0xe, &data16)); 6155 dsc_cbp->heye_right = data16; 6156 SOC_IF_ERROR_RETURN 6157 (phy82328_serdes_rdbl_uc_var(unit, port, pc, 0xf, &data16)); 6158 dsc_cbp->veye_upper = data16; 6159 SOC_IF_ERROR_RETURN 6160 (phy82328_serdes_rdbl_uc_var(unit, port, pc, 0x10, &data16)); 6161 dsc_cbp->veye_lower = data16; 6162 } 6163 /* Restore to default single port register access */ 6164 if (PHY82328_SINGLE_PORT_MODE(pc)) { 6165 SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, side, PHY82328_ALL_LANES)); 6166 } 6167 SOC_IF_ERROR_RETURN( 6168 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE)); 6169 if (!is_micro_stopped) { 6170 SOC_IF_ERROR_RETURN( 6171 phy82328_serdes_pmd_uc_cmd(unit, port, pc, PHY82328_CMD_UC_CTRL, PHY82328_CMD_UC_CTRL_RESUME, 2000)); 6172 } 6173 6174 /* display */ 6175 LOG_CLI((BSL_META_U(unit, 6176 "\nDSC parameters for port %d\n"), port)); 6177 6178 LOG_CLI((BSL_META_U(unit, 6179 "SNO OSR SIGDET UCV_CON RXLCK RXPPM CLK90 CLKP1 " 6180 "PFMAIN PFLOW DCOFFSET VGA P1LVLCTRL DFE1 DFE2 " 6181 "DFE3 DFE4 DFE5 PE ZE ME PO ZO MO TXPPM PRE " 6182 "MAIN POST1 POST2 \n"))); 6183 for (i = 0; i < lanes; i++) { 6184 dsc_cbp = &(dsc_cb[i]); 6185 LOG_CLI((BSL_META_U(unit, 6186 "%03d %03d %06d %07d %05d %05d %05d %05d %06d %05d %08d " 6187 "%03d %09d %04d %04d %04d %04d %04d %03d %03d %03d %03d" 6188 "%03d %03d %04d %03d %04d %04d %04d \n"), 6189 i, dsc_cbp->osr_mode, dsc_cbp->sig_det, dsc_cbp->ucv_config, 6190 dsc_cbp->rx_lock, dsc_cbp->rx_ppm, 6191 dsc_cbp->clk90, dsc_cbp->clkp1, 6192 dsc_cbp->pf_main, dsc_cbp->pf_low, 6193 dsc_cbp->dc_offset,dsc_cbp->vga,dsc_cbp->p1_lvl_ctrl, 6194 dsc_cbp->dfe1, dsc_cbp->dfe2, 6195 dsc_cbp->dfe3,dsc_cbp->dfe4,dsc_cbp->dfe5, 6196 dsc_cbp->pe,dsc_cbp->ze,dsc_cbp->me, dsc_cbp->po, 6197 dsc_cbp->zo, dsc_cbp->mo, 6198 dsc_cbp->tx_ppm, dsc_cbp->txfir_pre, dsc_cbp->txfir_main, 6199 dsc_cbp->txfir_post1, dsc_cbp->txfir_post2)); 6200 } 6201 return SOC_E_NONE; 6202 } 6203 6204 6205 STATIC int32 6206 phy_82328_diag_ctrl(int32 unit, soc_port_t port, uint32 inst, int32 op_type, int32 op_cmd, 6207 void *arg) 6208 { 6209 int32 lane; 6210 int32 intf; 6211 int32 rv = SOC_E_NONE; 6212 6213 lane = PHY_DIAG_INST_LN(inst); 6214 intf = PHY_DIAG_INST_INTF(inst); 6215 if (intf == PHY_DIAG_INTF_DFLT) { 6216 intf = PHY_DIAG_INTF_LINE; 6217 } 6218 6219 switch (op_cmd) { 6220 case PHY_DIAG_CTRL_DSC: 6221 rv = _phy_82328_diag_dsc(unit, port, intf, lane); 6222 break; 6223 case PHY_DIAG_CTRL_EYE_ENABLE_LIVELINK: 6224 case PHY_DIAG_CTRL_EYE_DISABLE_LIVELINK: 6225 case PHY_DIAG_CTRL_EYE_CLEAR_LIVELINK: 6226 case PHY_DIAG_CTRL_EYE_START_LIVELINK: 6227 case PHY_DIAG_CTRL_EYE_STOP_LIVELINK: 6228 case PHY_DIAG_CTRL_EYE_READ_LIVELINK: 6229 case PHY_DIAG_CTRL_EYE_GET_INIT_VOFFSET: 6230 case PHY_DIAG_CTRL_EYE_SET_HOFFSET: 6231 case PHY_DIAG_CTRL_EYE_SET_VOFFSET: 6232 case PHY_DIAG_CTRL_EYE_GET_MAX_LEFT_HOFFSET: 6233 case PHY_DIAG_CTRL_EYE_GET_MAX_RIGHT_HOFFSET: 6234 case PHY_DIAG_CTRL_EYE_GET_MIN_VOFFSET: 6235 case PHY_DIAG_CTRL_EYE_GET_MAX_VOFFSET: 6236 case PHY_DIAG_CTRL_EYE_MARGIN_VEYE: 6237 case PHY_DIAG_CTRL_EYE_MARGIN_HEYE_LEFT: 6238 case PHY_DIAG_CTRL_EYE_MARGIN_HEYE_RIGHT: 6239 rv = SOC_E_UNAVAIL; 6240 break; 6241 case PHY_DIAG_CTRL_START_FAST_EYESCAN: 6242 rv = _phy_82328_diag_eyescan(unit, port, inst); 6243 break; 6244 6245 default: 6246 if (op_type == PHY_DIAG_CTRL_SET) { 6247 SOC_IF_ERROR_RETURN 6248 (_phy_82328_control_set(unit, port, intf, lane, op_cmd, PTR_TO_INT(arg))); 6249 } else if (op_type == PHY_DIAG_CTRL_GET) { 6250 SOC_IF_ERROR_RETURN 6251 (_phy_82328_control_get(unit, port, intf, lane, op_cmd, (uint32 *)arg)); 6252 } else { 6253 LOG_ERROR(BSL_LS_SOC_PHY, 6254 (BSL_META_U(unit, 6255 "82328 diag_ctrl bad operation: u=%d p=%d ctrl=0x%x\n"), 6256 unit, port, op_cmd)); 6257 rv = SOC_E_UNAVAIL; 6258 } 6259 break; 6260 } 6261 return rv; 6262 } 6263 6264 /* 6265 * Function: 6266 * phy_82328_ability_remote_get 6267 * Purpose: 6268 * Get the device's complete abilities. 6269 * Parameters: 6270 * unit - StrataSwitch unit #. 6271 * port - StrataSwitch port #. 6272 * ability - return device's abilities. 6273 * Returns: 6274 * SOC_E_XXX 6275 */ 6276 6277 STATIC int 6278 phy_82328_ability_remote_get(int unit, soc_port_t port, 6279 soc_port_ability_t *ability) 6280 { 6281 int an, an_done; 6282 uint16 pause_adv; 6283 soc_port_mode_t mode; 6284 phy_ctrl_t *pc, *int_pc; 6285 phy82328_intf_cfg_t *line_intf; 6286 6287 if (ability == NULL) { 6288 return SOC_E_PARAM; 6289 } 6290 6291 /* Only firmware has visibility into remote ability */ 6292 sal_memset(ability, 0, sizeof(soc_port_ability_t)); 6293 6294 pc = EXT_PHY_SW_STATE(unit, port); 6295 line_intf = &(LINE_INTF(pc)); 6296 if ( (line_intf->type != SOC_PORT_IF_CR4) 6297 && (line_intf->type != SOC_PORT_IF_CR) 6298 && (line_intf->type != SOC_PORT_IF_KR4) 6299 && (line_intf->type != SOC_PORT_IF_KR) 6300 && (line_intf->type != SOC_PORT_IF_GMII) 6301 && (line_intf->type != SOC_PORT_IF_SGMII)) { 6302 return SOC_E_NONE; 6303 } 6304 6305 if (line_intf->type == SOC_PORT_IF_GMII) { 6306 int_pc = INT_PHY_SW_STATE(unit, port); 6307 if (int_pc) { 6308 SOC_IF_ERROR_RETURN(PHY_ABILITY_REMOTE_GET(int_pc->pd, unit, port, ability)); 6309 } 6310 return SOC_E_NONE; 6311 } 6312 6313 ability->speed_half_duplex = SOC_PA_ABILITY_NONE; 6314 6315 mode = 0; 6316 /* Return what the firmware is setting */ 6317 /* If an done, then return the speed for the port */ 6318 SOC_IF_ERROR_RETURN(phy_82328_an_get(unit, port, &an, &an_done)); 6319 if (an && an_done) { 6320 if(PHY82328_SINGLE_PORT_MODE(pc)) { 6321 ability->speed_full_duplex = SOC_PA_SPEED_40GB; 6322 } 6323 else { 6324 ability->speed_full_duplex = SOC_PA_SPEED_10GB; 6325 } 6326 6327 mode = 0; 6328 SOC_IF_ERROR_RETURN 6329 (READ_PHY82328_MMF_AN_REG(unit, pc, IEEE1_AN_BLK_AN_LP_BASE_PAGE_ABILITY_1_REG, &pause_adv)); 6330 switch (pause_adv & QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_MASK) { 6331 case (1<<QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT): /*7.0x0010.10 1*/ 6332 mode = SOC_PA_PAUSE_TX; 6333 break; 6334 case (1<<(QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT+1)): /*7.0x0010.11 1*/ 6335 mode = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 6336 break; 6337 case (1<<(QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT+1)) | 6338 (1<<QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT):/*7.0x0010.11:10 1*/ 6339 mode = SOC_PA_PAUSE_RX; 6340 break; 6341 default: 6342 mode = 0; 6343 break; 6344 } 6345 ability->pause = mode; 6346 } 6347 LOG_INFO(BSL_LS_SOC_PHY, 6348 (BSL_META_U(unit, 6349 "phy_82328_ability_remote_get: u=%d p=%d speed(FD)=0x%x pause=0x%x\n"), 6350 unit, port, ability->speed_full_duplex, ability->pause)); 6351 return SOC_E_NONE; 6352 } 6353 6354 /* 6355 * Function: 6356 * phy_82328_precondition_before_probe 6357 * Purpose: 6358 * When the device is in 40G, ie. after a power reset, and the 10G 6359 * port being probed does not have the 40G address in PRTAD, the 6360 * device will not respond until the port that has the 40G address 6361 * is probed. To avoid not programming ports correctly, make 6362 * sure the device is in quad (4x10G) PMD mode when the SDK port is 10G. 6363 * Need to set "port_phy_precondition_before_probe_xe0/4" in config file. 6364 * Parameters: 6365 * unit - StrataSwitch unit #. 6366 * pc - phy ctrl descriptor. 6367 * Returns: 6368 * SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error> 6369 */ 6370 6371 STATIC int32 6372 phy_82328_precondition_before_probe(int32 unit, phy_ctrl_t *pc) 6373 { 6374 int32 ids; 6375 int32 rv = SOC_E_NOT_FOUND; 6376 uint16 pmd_ctrl; 6377 uint16 id0, id1; 6378 uint16 saved_phy_id; 6379 /* Not required when the port is single PMD */ 6380 if (PHY82328_SINGLE_PORT_MODE(pc)) { 6381 LOG_INFO(BSL_LS_SOC_PHY, 6382 (BSL_META_U(unit, 6383 "PMD must not be called when in single PMD\n"))); 6384 return rv; 6385 } 6386 saved_phy_id = pc->phy_id; 6387 6388 /* Look for first address that responds */ 6389 for (ids = 0; ids < 4; ids++) { 6390 6391 pc->phy_id = (saved_phy_id & ~0x3) + ids; 6392 LOG_INFO(BSL_LS_SOC_PHY, 6393 (BSL_META_U(unit, 6394 "Try device with address %x\n"), pc->phy_id)); 6395 6396 /* 6397 * Make sure the device has the correct dev IDs 6398 * Note that this is being called either because the soc probe found 6399 * the ids or there was an id override. In the later case, the device 6400 * might not have the 82328 ids so this PMD setup will not be supported 6401 */ 6402 id0 = 0; 6403 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 6404 IEEE0_BLK_PMA_PMD_PMD_IDENTIFIER_REGISTER_0, 6405 &id0); 6406 if (id0 != 0xae02) { 6407 continue; 6408 } 6409 id1 = 0; 6410 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 6411 IEEE0_BLK_PMA_PMD_PMD_IDENTIFIER_REGISTER_1, 6412 &id1); 6413 if (id1 != 0x5210) { 6414 continue; 6415 } 6416 6417 /* Read device ids correctly so use this address to make sure device is in 10G */ 6418 pmd_ctrl = 0; 6419 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 6420 MGT_TOP_SINGLE_PMD_CTRL, &pmd_ctrl); 6421 if (pmd_ctrl & MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_SINGLE_PMD_MODE_MASK) { 6422 LOG_INFO(BSL_LS_SOC_PHY, 6423 (BSL_META_U(unit, 6424 "Device responded to address %x. Setting quad PMD mode\n"), 6425 pc->phy_id)); 6426 pmd_ctrl = 0; /* Clear single PMD */ 6427 SOC_IF_ERROR_RETURN( 6428 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 6429 MGT_TOP_SINGLE_PMD_CTRL , pmd_ctrl, 6430 MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_SINGLE_PMD_MODE_MASK)); 6431 } 6432 /* Found the address that responds and the device now is in 4x10G */ 6433 rv = SOC_E_NONE; 6434 break; 6435 } 6436 6437 pc->phy_id = saved_phy_id; 6438 6439 return rv; 6440 } 6441 6442 6443 /* 6444 * Function: 6445 * phy_82328_multi_get 6446 * Purpose: 6447 * Multi data read interface through device I2C 6448 * Parameters: 6449 * unit - StrataSwitch unit # 6450 * port - Port number 6451 * flags - flags passed in the transfer 6452 * dev_adr - Device address from which data need to be read. 6453 * offset - Starting addres from which data read starts. 6454 * max_size - Maximum Number of bytes to read 6455 * data - data buffer to receive the data 6456 * actual_size - Actual received number of byte 6457 * Returns: 6458 * SOC_E_XXX 6459 */ 6460 6461 STATIC int 6462 phy_82328_multi_get(int unit, soc_port_t port, uint32 flags, 6463 uint32 dev_addr, uint32 offset, int max_size, uint8 *data, 6464 int *actual_size) 6465 { 6466 int rv; 6467 rv = phy_82328_i2cdev_read(unit, port, (int)dev_addr, (int)offset, max_size, 6468 data); 6469 if (SOC_FAILURE(rv)) { 6470 *actual_size = 0; 6471 return SOC_E_FAIL; 6472 } 6473 *actual_size = max_size; 6474 return SOC_E_NONE; 6475 } 6476 6477 /* 6478 * Variable: phy_82328drv_xe 6479 * Purpose: Phy driver callouts for a phy 82328 6480 * Notes: 6481 */ 6482 phy_driver_t phy_82328drv_xe = { 6483 "82328 40-Gigabit PHY Driver", 6484 phy_82328_init, /* phy_init */ 6485 phy_null_reset, /* phy_reset */ 6486 phy_82328_link_get, /* phy_link_get */ 6487 phy_82328_enable_set, /* phy_enable_set */ 6488 phy_null_enable_get, /* phy_enable_get */ 6489 phy_null_duplex_set, /* phy_duplex_set */ 6490 phy_null_duplex_get, /* phy_duplex_get */ 6491 phy_82328_speed_set, /* phy_speed_set */ 6492 phy_82328_speed_get, /* phy_speed_get */ 6493 phy_null_set, /* phy_master_set */ 6494 phy_null_zero_get, /* phy_master_get */ 6495 phy_82328_an_set, /* phy_an_set */ 6496 phy_82328_an_get, /* phy_an_get */ 6497 phy_null_mode_set, /* phy_adv_local_set */ 6498 phy_null_mode_get, /* phy_adv_local_get */ 6499 phy_null_mode_get, /* phy_adv_remote_get */ 6500 phy_82328_lb_set, /* phy_lb_set */ 6501 phy_82328_lb_get, /* phy_lb_get */ 6502 phy_82328_interface_set, /* phy_interface_set */ 6503 phy_82328_interface_get, /* phy_interface_get */ 6504 phy_null_mode_get, /* phy_ability */ 6505 NULL, /* phy_linkup_evt */ 6506 NULL, /* phy_linkdn_evt */ 6507 phy_null_mdix_set, /* phy_mdix_set */ 6508 phy_null_mdix_get, /* phy_mdix_get */ 6509 phy_null_mdix_status_get, /* phy_mdix_status_get */ 6510 #if 1 6511 NULL, /* phy_medium_config_set */ 6512 NULL, /* phy_medium_config_get */ 6513 phy_null_medium_get, /* phy_medium_get */ 6514 #endif 6515 NULL, /* phy_cable_diag */ 6516 NULL, /* phy_link_change */ 6517 phy_82328_control_set, /* phy_control_set */ 6518 phy_82328_control_get, /* phy_control_get */ 6519 phy_82328_reg_read, /* phy_reg_read */ 6520 phy_82328_reg_write, /* phy_reg_write */ 6521 NULL, /* phy_reg_modify */ 6522 NULL, /* phy_notify */ 6523 phy_82328_probe, /* phy_probe */ 6524 phy_82328_ability_advert_set,/* phy_ability_advert_set */ 6525 phy_82328_ability_advert_get,/* phy_ability_advert_get */ 6526 phy_82328_ability_remote_get,/* phy_ability_remote_get */ 6527 phy_82328_ability_local_get, /* phy_ability_local_get */ 6528 phy_82328_firmware_set, /* phy_firmware_set */ 6529 NULL, /* phy_timesync_config_set */ 6530 NULL, /* phy_timesync_config_get */ 6531 NULL, /* phy_timesync_control_set */ 6532 NULL, /* phy_timesync_control_get */ 6533 phy_82328_diag_ctrl, /* phy_diag_ctrl */ 6534 NULL, /* pd_lane_control_set */ 6535 NULL, /* pd_lane_control_get */ 6536 NULL, /* pd_lane_reg_read */ 6537 NULL, /* pd_lane_reg_write */ 6538 NULL, /* pd_oam_config_set */ 6539 NULL, /* pd_oam_config_get */ 6540 NULL, /* pd_oam_control_set */ 6541 NULL, /* pd_oam_control_get */ 6542 NULL, /* pd_timesync_enhanced_capture_get */ 6543 phy_82328_multi_get, /* pd_multi_get */ 6544 phy_82328_precondition_before_probe /* pd_precondition_before_probe */ 6545 6546 }; 6547 #else /* INCLUDE_PHY_82328 */ 6548 int _phy_82328_not_empty; 6549 #endif /* INCLUDE_PHY_82328 */