phy84740.c (329682B)
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: phy84740.c 8 * Purpose: Phys Driver support for Broadcom 84740 40Gig 9 * transceiver :XLAUI system side and PPI Line interface. 10 * Note: 11 */ 12 13 #include <sal/types.h> 14 15 #include <soc/drv.h> 16 #include <soc/debug.h> 17 #include <soc/error.h> 18 #include <soc/phyreg.h> 19 20 #include <soc/phy.h> 21 #include <soc/phy/phyctrl.h> 22 #include <soc/phy/drv.h> 23 #include <shared/bsl.h> 24 #include "phydefs.h" /* Must include before other phy related includes */ 25 26 #if defined(INCLUDE_PHY_84740) 27 #include "phyconfig.h" /* Must be the first phy include after phydefs.h */ 28 #include "phyident.h" 29 #include "phyreg.h" 30 #include "phynull.h" 31 #include "phyxehg.h" 32 #include "phy84740.h" 33 /* 34 * SPI-ROM Program related defs 35 */ 36 #define SPI_CTRL_1_L 0xC000 37 #define SPI_CTRL_1_H 0xC002 38 #define SPI_CTRL_2_L 0xC400 39 #define SPI_CTRL_2_H 0xC402 40 #define SPI_TXFIFO 0xD000 41 #define SPI_RXFIFO 0xD400 42 #define WR_CPU_CTRL_REGS 0x11 43 #define RD_CPU_CTRL_REGS 0xEE 44 #define WR_CPU_CTRL_FIFO 0x66 45 46 /* 47 * SPI Controller Commands(Messages). 48 */ 49 #define MSGTYPE_HWR 0x40 50 #define MSGTYPE_HRD 0x80 51 #define WRSR_OPCODE 0x01 52 #define WR_OPCODE 0x02 53 #define WRDI_OPCODE 0x04 54 #define RDSR_OPCODE 0x05 55 #define WREN_OPCODE 0x06 56 #define WR_BLOCK_SIZE 0x40 57 #define TOTAL_WR_BYTE 0x4000 58 59 #define WR_TIMEOUT 1000000 60 61 /* CL73 autoneg */ 62 #define AN_ADVERT_40GCR4 (1 << 9) 63 #define AN_ADVERT_40GKR4 (1 << 8) 64 #define AN_ADVERT_10GKR (1 << 7) 65 #define AN_ADVERT_1GKX (1 << 5) 66 67 /* PRBS */ 68 #define PHY84740_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS 0x0135 69 #define PHY84740_FORTYG_SQ_WAVE_TESTING_CONTROL_REGISTER 0x05dd 70 #define PHY84740_UDRCD_PRBS20_CONTROL_REGISTER 0xcd60 71 #define PHY84740_FORTYG_PRBS_RX_TESTING_ERROR_COUNTER_LANE0 0x06a4 72 73 #define PHY84740_40G_PRBS31 (1 << 7) 74 #define PHY84740_40G_PRBS9 (1 << 6) 75 76 #define PHY84740_40G_SYS_PRBS31 (0x6) 77 #define PHY84740_40G_SYS_PRBS23 (0x5) 78 #define PHY84740_40G_SYS_PRBS15 (0x4) 79 #define PHY84740_40G_SYS_PRBS11 (0x3) 80 #define PHY84740_40G_SYS_PRBS9 (0x2) 81 #define PHY84740_40G_SYS_PRBS7 (0x1) 82 #define PHY84740_40G_SYS_PRBS_POLY_MASK (0x7007) 83 #define PHY84740_40G_SYS_PRBS_MASK (0x7) 84 #define PHY84740_40G_SYS_PRBS_ENABLE (0x0005) 85 #define PHY84740_40G_SYS_PRBS_ENABLE_MASK (0x0005) 86 #define PHY84740_40G_SYS_PRBS_LOCK_VALUE (0x8000) 87 #define PHY84740_40G_SYS_PRBS_LOCK_MASK (0xf000) 88 #define PHY84740_40G_SYS_PRBS_ERR_MASK (0x0fff) 89 #define PHY84740_40G_SYS_REP_MODE_ENABLE (0x6) 90 #define PHY84740_RX_REPEATER_MASK (1 << 1) 91 #define PHY84740_TX_REPEATER_MASK (1 << 2) 92 #define PHY84740_TX_REPEATER_ENABLE (1 << 2) 93 94 95 #define PHY84740_40G_PRBS_TX_ENABLE (1 << 3) 96 #define PHY84740_40G_PRBS_RX_ENABLE (1 << 0) 97 #define PHY84740_40G_PRBS_ENABLE (PHY84740_40G_PRBS_RX_ENABLE | \ 98 PHY84740_40G_PRBS_TX_ENABLE) 99 100 #define PHY84740_FORTYG_PRBS_RECEIVE_ERROR_COUNTER_LANE0 0x0140 101 #define PHY84740_USER_PRBS_CONTROL_0_REGISTER 0xCD14 102 #define PHY84740_USER_PRBS_TX_INVERT (1 << 4) 103 #define PHY84740_USER_PRBS_RX_INVERT (1 << 15) 104 #define PHY84740_USER_PRBS_INVERT (1 << 4 | 1 << 15) 105 #define PHY84740_USER_PRBS_ENABLE (1 << 7) 106 #define PHY84740_USER_PRBS_TYPE_MASK (0x7) 107 108 #define PHY84740_USER_PRBS_STATUS_0_REGISTER 0xCD15 109 #define PHY84740_GENSIG_8071_REGISTER 0xCD16 110 #define PHY84740_RESET_CONTROL_REGISTER 0xCD17 111 112 /* Module auto detect status */ 113 #define PHY84740_MOD_AUTO_DETECT_STS_REG 0xc82b 114 #define PHY84740_MOD_AUTO_DETECT_STS_NOT_DONE (1 << 15) 115 #define PHY84740_MOD_AUTO_DETECT_STS_SFP_EN (1 << 10) 116 #define PHY84740_MOD_AUTO_DETECT_STS_I2C_FAIL (1 << 9) 117 #define PHY84740_MOD_AUTO_DETECT_STS_NOT_RES (1 << 0) 118 119 /* Optical config */ 120 #define PHY84740_PMAD_OPTICAL_CFG_MOD_PRESENCE (1 << 3) 121 122 /* General purpose register */ 123 #define PHY84740_PMAD_GEN_PURPOSE_REG 0xc710 124 #define PHY84740_PMAD_GEN_PURPOSE_MOD_AUTO_DETECT_EN (1 << 2) 125 126 /* Polarity config */ 127 #define POL_CONFIG_LANE_WIDTH 0x4 128 #define POL_CONFIG_LANE_MASK(_ln) (0xf << ((_ln) * POL_CONFIG_LANE_WIDTH)) 129 #define POL_CONFIG_ALL_LANES 1 130 /* 131 * When a port is being flexed between 40G->10G, 132 * the polarity config syntax can be in 133 * 40G syntax for first lane, so there is a need to parse 134 * both 10G and 40G polarity config syntax in 10G. 135 */ 136 #define PHY84740_LN(_pc) ((_pc)->phy_id & 0x3) 137 #define PHY84740_POL_MASK(_pc) POL_CONFIG_LANE_MASK(PHY84740_LN(_pc)) 138 #define PHY84740_10G_POL_CFG_GET(_pc, _pol) \ 139 (((_pol) == POL_CONFIG_ALL_LANES) || \ 140 (((_pol) & PHY84740_POL_MASK(_pc)) == PHY84740_POL_MASK(_pc))) 141 142 /* I2C related defines */ 143 #define PHY84740_BSC_XFER_MAX 0x1F9 144 #define PHY84740_BSC_WR_MAX 16 145 #define PHY84740_WRITE_START_ADDR 0x8007 146 #define PHY84740_READ_START_ADDR 0x8007 147 #define PHY84740_WR_FREQ_400KHZ 0x0100 148 #define PHY84740_2W_STAT 0x000C 149 #define PHY84740_2W_STAT_IDLE 0x0000 150 #define PHY84740_2W_STAT_COMPLETE 0x0004 151 #define PHY84740_2W_STAT_IN_PRG 0x0008 152 #define PHY84740_2W_STAT_FAIL 0x000C 153 #define PHY84740_BSC_WRITE_OP 0x22 154 #define PHY84740_BSC_READ_OP 0x2 155 #define PHY84740_I2CDEV_WRITE 0x1 156 #define PHY84740_I2CDEV_READ 0x0 157 #define PHY84740_I2C_8BIT 0 158 #define PHY84740_I2C_16BIT 1 159 #define PHY84740_I2C_TEMP_RAM 0xE 160 #define PHY84740_I2C_OP_TYPE(access_type,data_type) \ 161 ((access_type) | ((data_type) << 8)) 162 #define PHY84740_I2C_ACCESS_TYPE(op_type) ((op_type) & 0xff) 163 #define PHY84740_I2C_DATA_TYPE(op_type) (((op_type) >> 8) & 0xff) 164 165 /* preemphasis control */ 166 #define PHY84740_PREEMPH_CTRL_POST_TAP2_SHFT 16 167 #define PHY84740_PREEMP_GET_POST_TAP2(_val)\ 168 (((_val) >> PHY84740_PREEMPH_CTRL_POST_TAP2_SHFT) & 0x7) 169 #define PHY84740_PREEMPH_REG_POST_TAP2_MASK (0x7 << PHY84740_PREEMPH_REG_POST_TAP2_SHFT) 170 #define PHY84740_PREEMPH_REG_POST_TAP2_SHFT 0 171 #define PHY84740_PREEMPH_CTRL_FORCE_SHFT 15 172 #define PHY84740_PREEMPH_GET_FORCE(_val) \ 173 (((_val) >> PHY84740_PREEMPH_CTRL_FORCE_SHFT) & 1) 174 #define PHY84740_PREEMPH_CTRL_POST_TAP_SHFT 10 175 #define PHY84740_PREEMPH_GET_POST_TAP(_val) \ 176 (((_val) >> PHY84740_PREEMPH_CTRL_POST_TAP_SHFT) & 0x1f) 177 #define PHY84740_PREEMPH_CTRL_PRE_TAP_SHFT 0 178 #define PHY84740_PREEMPH_GET_PRE_TAP(_val) \ 179 (((_val) >> PHY84740_PREEMPH_CTRL_PRE_TAP_SHFT) & 0xf) 180 #define PHY84740_PREEMPH_CTRL_MAIN_TAP_SHFT 4 181 #define PHY84740_PREEMPH_GET_MAIN_TAP(_val) \ 182 (((_val) >> PHY84740_PREEMPH_CTRL_MAIN_TAP_SHFT) & 0x3f) 183 #define PHY84740_PREEMPH_REG_FORCE_MASK (1 << 8) 184 #define PHY84740_PREEMPH_REG_POST_TAP_SHFT 4 185 #define PHY84740_PREEMPH_REG_POST_TAP_MASK (0xf << PHY84740_PREEMPH_REG_POST_TAP_SHFT) 186 #define PHY84740_PREEMPH_REG_PRE_TAP_SHFT 0 187 #define PHY84740_PREEMPH_REG_PRE_TAP_MASK (0x7 << PHY84740_PREEMPH_REG_PRE_TAP_SHFT) 188 #define PHY84740_PREEMPH_REG_MAIN_TAP_SHFT 11 189 #define PHY84740_PREEMPH_REG_MAIN_TAP_MASK (0x1f << PHY84740_PREEMPH_REG_MAIN_TAP_SHFT) 190 #define PHY84740_PREEMPH_REG_TX_PWRDN_MASK (0x1 << 10) 191 192 /* Misc. */ 193 #define PHY84740_AN_SPEED_1G_MASK 0x11 194 #define PHY84740_AN_SPEED_10G_MASK 0x44 195 #define PHY84740_UCODE_DEVID_ADDR 0x7FF9 196 197 #define PHY84740_SINGLE_PORT_MODE(_pc) \ 198 (SOC_INFO((_pc)->unit).port_num_lanes[(_pc)->port] >= 4) 199 #define PHY84740_EDC_MODE_MASK 0xff 200 #define PHY84740_ID_84740 0x84740 201 #define PHY84740_ID_84064 0x84064 202 #define PHY84740_ID_84754 0x84754 203 #define PHY84740_ID_84753 0x84753 204 #define PHY84740_ID_84752 0x84752 205 206 /* Other variants */ 207 #define PHY84740_ID_84780 0x84780 208 #define PHY84740_ID_84784 0x84784 209 #define PHY84740_ID_84758 0x84758 210 #define PHY84740_ID_84164 0x84164 211 #define PHY84740_ID_84168 0x84168 212 #define PHY84740_ID_84318 0x84318 213 214 #define PHY84740_IS_QUADRA(devid)\ 215 ((devid) == PHY84740_ID_84780 ||\ 216 (devid) == PHY84740_ID_84784 ||\ 217 (devid) == PHY84740_ID_84758 ||\ 218 (devid) == PHY84740_ID_84164 ||\ 219 (devid) == PHY84740_ID_84168 ||\ 220 (devid) == PHY84740_ID_84318) 221 222 #define PHY84740_IS_QUADRA_BACKPLANE(devid)\ 223 ((devid) == PHY84740_ID_84164 ||\ 224 (devid) == PHY84740_ID_84168 ) 225 226 #define NUM_LANES 4 227 228 /* typedefs */ 229 typedef struct { 230 int rx_los; 231 int rx_los_invert; 232 int mod_abs; 233 int mod_abs_invert; 234 int p2l_map[NUM_LANES]; /* index: physical lane, array element: logical lane */ 235 int pcs_repeater; 236 int reverse_mode; 237 int mod_auto_detect; 238 int mod_auto_detect_msg; 239 int software_rx_los; 240 int fcmap_passthrough; 241 int single_lpmode; 242 int skip_fw_dload; 243 } PHY84740_DEV_DESC_t; 244 245 /* device field macros */ 246 #define RX_LOS(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->rx_los) 247 #define RX_LOS_INVERT(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->rx_los_invert) 248 #define MOD_ABS(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->mod_abs) 249 #define MOD_ABS_INVERT(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->mod_abs_invert) 250 #define P2L_MAP(_pc,_ix) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->p2l_map[(_ix)]) 251 #define PCS_REPEATER(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->pcs_repeater) 252 #define REVERSE_MODE(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->reverse_mode) 253 #define MOD_AUTO_DETECT(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->mod_auto_detect) 254 #define MOD_AUTO_DETECT_MSG(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->mod_auto_detect_msg) 255 #define SOFTWARE_RX_LOS(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->software_rx_los) 256 #define FCMAP_PASSTHROUGH(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->fcmap_passthrough) 257 #define SINGLE_LPMODE(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->single_lpmode) 258 #define SKIP_FW_DLOAD(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->skip_fw_dload) 259 260 #define PHY84740_FCS_ERROR_WAR 261 262 /* callback to deliever the firmware by application 263 * return value: TRUE successfully delivered 264 * FALSE fail to deliver 265 * 266 * Example: 267 * 268 * int user_firmware_send (int unit,int port,int flag,unsigned char **data,int *len) 269 * { 270 * *data = phy84740_ucode_bin; 271 * *len = phy84740_ucode_bin_len; 272 LOG_WARN(BSL_LS_SOC_PHY, 273 (BSL_META_U(unit, 274 "port %d: user firmware hook routine called\n"),port)); 275 * return TRUE; 276 * } 277 * Then initialize the function pointer before the BCM port initialization: 278 * phy_84740_uc_firmware_hook = user_firmware_send; 279 */ 280 int (*phy_84740_uc_firmware_hook) (int unit, /* switch number */ 281 int port, /* port number */ 282 int flag, /* any information need to ba passed. Not used for now */ 283 unsigned char **addr, /* starting address of delivered firmware */ 284 int *len /* length of the firmware */ 285 ) = NULL; 286 287 static int write_message(int unit, phy_ctrl_t *pc, uint16 wrdata, 288 uint16 *rddata); 289 290 STATIC int phy_84740_speed_get(int, soc_port_t, int *); 291 STATIC int 292 _phy_84740_firmware_to_rom(int unit, int port, int offset, uint8 *array, 293 int datalen); 294 STATIC int _phy84740_mdio_lane_firmware_download(int unit, int port, 295 phy_ctrl_t *pc, 296 uint8 *new_fw, 297 uint32 fw_length); 298 STATIC void _phy_84740_decode_syncout_mode(uint16 value, 299 soc_port_phy_timesync_syncout_mode_t 300 *mode); 301 STATIC void _phy_84740_encode_syncout_mode(soc_port_phy_timesync_syncout_mode_t 302 mode, uint16 *value); 303 STATIC void _phy_84740_decode_framesync_mode(uint16 value, 304 soc_port_phy_timesync_framesync_mode_t 305 *mode); 306 STATIC void 307 _phy_84740_encode_framesync_mode(soc_port_phy_timesync_framesync_mode_t mode, 308 uint16 *value); 309 STATIC void _phy_84740_decode_gmode(uint16 value, 310 soc_port_phy_timesync_global_mode_t *mode); 311 STATIC void _phy_84740_encode_gmode(soc_port_phy_timesync_global_mode_t mode, 312 uint16 *value); 313 STATIC void _phy_84740_decode_ingress_message_mode(uint16 value, int offset, 314 soc_port_phy_timesync_event_message_ingress_mode_t 315 *mode); 316 STATIC void _phy_84740_decode_egress_message_mode(uint16 value, int offset, 317 soc_port_phy_timesync_event_message_egress_mode_t 318 *mode); 319 320 STATIC void 321 _phy_84740_encode_ingress_message_mode 322 (soc_port_phy_timesync_event_message_ingress_mode_t mode, int offset, uint16 *value); 323 STATIC void 324 _phy_84740_encode_egress_message_mode 325 (soc_port_phy_timesync_event_message_egress_mode_t mode, int offset, uint16 *value); 326 STATIC int phy_84740_tx_polarity_flip_set(int unit, int port, uint32 value); 327 STATIC int phy_84740_rx_polarity_flip_set(int unit, int port, uint32 value); 328 STATIC int phy_84740_enable_set(int unit, soc_port_t port, int enable); 329 extern unsigned char phy84740_ucode_bin[]; 330 extern unsigned int phy84740_ucode_bin_len; 331 extern unsigned char phy84754_ucode_bin[]; 332 extern unsigned int phy84754_ucode_bin_len; 333 extern unsigned char phy84753_ucode_bin[]; 334 extern unsigned int phy84753_ucode_bin_len; 335 extern unsigned char phy84064_ucode_bin[]; 336 extern unsigned int phy84064_ucode_bin_len; 337 extern unsigned char phy84752_ucode_bin[]; 338 extern unsigned int phy84752_ucode_bin_len; 339 extern unsigned char phy84758_ucode_bin[]; 340 extern unsigned int phy84758_ucode_bin_len; 341 extern unsigned char phy84780_ucode_bin[]; 342 extern unsigned int phy84780_ucode_bin_len; 343 extern unsigned char phy84784_ucode_bin[]; 344 extern unsigned int phy84784_ucode_bin_len; 345 extern unsigned char phy84318_ucode_bin[]; 346 extern unsigned int phy84318_ucode_bin_len; 347 348 static char *dev_name_84740 = "BCM84740"; 349 static char *dev_name_84752 = "BCM84752"; 350 static char *dev_name_84753 = "BCM84753"; 351 static char *dev_name_84754 = "BCM84754"; 352 static char *dev_name_84064 = "BCM84064"; 353 static char *dev_name_84784 = "BCM84784"; 354 STATIC int 355 _phy_84740_config_devid(int unit, soc_port_t port, phy_ctrl_t *pc, 356 uint32 *devid) 357 { 358 uint16 data16; 359 360 if (soc_property_port_get(unit, port, spn_PHY_84740, FALSE)) { 361 *devid = PHY84740_ID_84740; 362 } else if (soc_property_port_get(unit, port, spn_PHY_84752, FALSE)) { 363 *devid = PHY84740_ID_84752; 364 } else if (soc_property_port_get(unit, port, spn_PHY_84753, FALSE)) { 365 *devid = PHY84740_ID_84753; 366 } else if (soc_property_port_get(unit, port, spn_PHY_84754, FALSE)) { 367 *devid = PHY84740_ID_84754; 368 } else if (soc_property_port_get(unit, port, spn_PHY_84064, FALSE)) { 369 *devid = PHY84740_ID_84064; 370 } else { 371 372 /* read Other chip id */ 373 SOC_IF_ERROR_RETURN 374 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc802, &data16)); 375 376 if (PHY84740_IS_QUADRA(0x80000 | data16)) { 377 *devid = 0x80000 | data16; 378 } else { 379 *devid = 0; 380 } 381 } 382 return SOC_E_NONE; 383 } 384 385 STATIC int 386 _phy_84740_single_to_quad_mode(int unit, soc_port_t port, phy_ctrl_t *pc) 387 { 388 int ix; 389 uint16 saved_phy_addr; 390 uint16 mask16; 391 uint16 data16; 392 uint32 devid; 393 394 if (pc == NULL) { 395 pc = EXT_PHY_SW_STATE(unit, port); 396 } 397 398 /* probe routine should block any invalid devids. 399 * devids should be always valid here 400 */ 401 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 402 (pc->unit, pc->port, pc, &devid)); 403 404 mask16 = PHY84740_PMAD_DAC_MODE_MASK | PHY84740_PMAD_BKPLANE_MODE_MASK; 405 if (devid == PHY84740_ID_84064) { 406 data16 = PHY84740_PMAD_BKPLANE_MODE_MASK; 407 } else { 408 data16 = 0; 409 } 410 411 /* config DAC mode/backplane mode first. This is a bcst register in single mode */ 412 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 413 (pc->unit, pc, PHY84740_PMAD_CHIP_MODE_REG, data16, 414 mask16)); 415 416 /* then configure quad chip mode */ 417 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 418 (pc->unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 0, 419 PHY84740_PMAD_CHIP_MODE_MASK)); 420 421 /* once this mode register is configured with quad mode, each lane is 422 * accessable by the lane specific MDIO address 423 */ 424 saved_phy_addr = pc->phy_id; 425 /* Reset all 4 lanes. Only after reset, the mode is actually switched */ 426 for (ix = 0; ix < 4; ix++) { 427 pc->phy_id = (saved_phy_addr & (~0x3)) + ix; 428 SOC_IF_ERROR_RETURN 429 (MODIFY_PHY84740_PMA_PMD_CTRLr(pc->unit, pc, 430 MII_CTRL_RESET, MII_CTRL_RESET)); 431 } 432 pc->phy_id = saved_phy_addr; 433 434 return SOC_E_NONE; 435 } 436 437 STATIC int _phy_84740_quad_to_single_mode(int unit, soc_port_t port) 438 { 439 int ix; 440 uint16 saved_phy_addr; 441 phy_ctrl_t *pc; 442 uint16 mask16; 443 uint16 data16; 444 uint32 devid; 445 446 pc = EXT_PHY_SW_STATE(unit, port); 447 448 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 449 (pc->unit, pc->port, pc, &devid)); 450 451 saved_phy_addr = pc->phy_id; 452 /* configure all four lanes to bcst mode */ 453 for (ix = 0; ix < 4; ix++) { 454 pc->phy_id = (saved_phy_addr & (~0x3)) + ix; 455 SOC_IF_ERROR_RETURN 456 (WRITE_PHY84740_MMF_PMA_PMD_REG(pc->unit, pc, 457 PHY84740_PMAD_BCST_REG, 0xffff)); 458 } 459 pc->phy_id = saved_phy_addr; 460 461 /* then configure single mode */ 462 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 463 (pc->unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 464 PHY84740_PMAD_MODE_40G, PHY84740_PMAD_CHIP_MODE_MASK)); 465 466 mask16 = PHY84740_PMAD_DAC_MODE_MASK | PHY84740_PMAD_BKPLANE_MODE_MASK; 467 if (devid == PHY84740_ID_84064) { 468 data16 = PHY84740_PMAD_BKPLANE_MODE_MASK; 469 } else { 470 data16 = 0; 471 } 472 473 /* config DAC mode and backplane mode for LR4/SR4 */ 474 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 475 (pc->unit, pc, PHY84740_PMAD_CHIP_MODE_REG, data16, 476 mask16)); 477 478 /* do a soft reset to switch to the configured mode 479 * The reset should also clear the bcst register configuration 480 */ 481 SOC_IF_ERROR_RETURN 482 (MODIFY_PHY84740_PMA_PMD_CTRLr(pc->unit, pc, 483 MII_CTRL_RESET, MII_CTRL_RESET)); 484 485 return SOC_E_NONE; 486 } 487 488 STATIC int 489 _phy84740_mdio_firmware_download(int unit, int port, phy_ctrl_t *pc, 490 uint8 *new_fw, uint32 fw_length) 491 { 492 uint16 data16; 493 uint16 mask16; 494 int lane; 495 int rv = SOC_E_NONE; 496 497 if (new_fw == NULL || fw_length == 0) { 498 LOG_WARN(BSL_LS_SOC_PHY, 499 (BSL_META_U(unit, 500 "u=%d p=%d MDIO firmware download: invalid firmware\n"), 501 unit, port)); 502 return SOC_E_NONE; 503 } 504 505 if (PHY84740_SINGLE_PORT_MODE(pc)) { 506 /* point to lane 0 */ 507 SOC_IF_ERROR_RETURN 508 (WRITE_PHY84740_MMF_PMA_PMD_REG 509 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 510 } 511 512 /* clear SPA ctrl reg bit 15 and bit 13. 513 * bit 15, 0-use MDIO download to SRAM, 1 SPI-ROM download to SRAM 514 * bit 13, 0 clear download done status, 1 skip download 515 */ 516 mask16 = (1 << 13) | (1 << 15); 517 data16 = 0; 518 SOC_IF_ERROR_RETURN 519 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_SPA_CTRL_REG, 520 data16, mask16)); 521 522 /* set SPA ctrl reg bit 14, 1 RAM boot, 0 internal ROM boot */ 523 mask16 = 1 << 14; 524 data16 = mask16; 525 SOC_IF_ERROR_RETURN 526 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_SPA_CTRL_REG, 527 data16, mask16)); 528 529 /* misc_ctrl1 reg bit 3 to 1 for 32k downloading size */ 530 if (PHY84740_SINGLE_PORT_MODE(pc)) { 531 for (lane = 0; lane < NUM_LANES; lane++) { 532 SOC_IF_ERROR_RETURN 533 (WRITE_PHY84740_MMF_PMA_PMD_REG 534 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, lane)); 535 mask16 = 1 << 3; 536 data16 = mask16; 537 SOC_IF_ERROR_RETURN 538 (MODIFY_PHY84740_MMF_PMA_PMD_REG 539 (unit, pc, PHY84740_PMAD_MISC_CTRL1_REG, data16, mask16)); 540 } 541 } else { 542 mask16 = 1 << 3; 543 data16 = mask16; 544 SOC_IF_ERROR_RETURN 545 (MODIFY_PHY84740_MMF_PMA_PMD_REG 546 (unit, pc, PHY84740_PMAD_MISC_CTRL1_REG, data16, mask16)); 547 } 548 if (PHY84740_SINGLE_PORT_MODE(pc)) { 549 /* apply bcst Reset to start download code from MDIO */ 550 SOC_IF_ERROR_RETURN 551 (WRITE_PHY84740_MMF_PMA_PMD_REG 552 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 553 } 554 SOC_IF_ERROR_RETURN(WRITE_PHY84740_PMA_PMD_CTRLr(unit, pc, 0x8000)); 555 556 /* wait for 2ms for M8051 start and 5ms to initialize the RAM */ 557 sal_usleep(10000); /* Wait for 10ms */ 558 559 if (PHY84740_SINGLE_PORT_MODE(pc)) { 560 for (lane = 0; lane < NUM_LANES; lane++) { 561 SOC_IF_ERROR_RETURN 562 (WRITE_PHY84740_MMF_PMA_PMD_REG 563 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, lane)); 564 /* download the firmware to the specific lane */ 565 rv = _phy84740_mdio_lane_firmware_download(unit, port, pc, new_fw, 566 fw_length); 567 } 568 569 /* point back to lane0 */ 570 SOC_IF_ERROR_RETURN 571 (WRITE_PHY84740_MMF_PMA_PMD_REG 572 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 573 } else { 574 SOC_IF_ERROR_RETURN 575 (_phy84740_mdio_lane_firmware_download 576 (unit, port, pc, new_fw, fw_length)); 577 } 578 return rv; 579 } 580 581 STATIC int 582 _phy84740_mdio_lane_firmware_download(int unit, int port, phy_ctrl_t *pc, 583 uint8 *new_fw, uint32 fw_length) 584 { 585 uint16 data16; 586 int j; 587 uint16 num_words; 588 589 /* Write Starting Address, where the Code will reside in SRAM */ 590 data16 = 0x8000; 591 SOC_IF_ERROR_RETURN 592 (WRITE_PHY84740_MMF_PMA_PMD_REG 593 (unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, data16)); 594 595 /* make sure address word is read by the micro */ 596 sal_udelay(10); /* Wait for 10us */ 597 598 /* Write SPI SRAM Count Size */ 599 data16 = (fw_length) / 2; 600 SOC_IF_ERROR_RETURN 601 (WRITE_PHY84740_MMF_PMA_PMD_REG 602 (unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, data16)); 603 604 /* make sure read by the micro */ 605 sal_udelay(10); /* Wait for 10us */ 606 607 /* Fill in the SRAM */ 608 num_words = (fw_length - 1); 609 for (j = 0; j < num_words; j += 2) { 610 /* Make sure the word is read by the Micro */ 611 sal_udelay(10); 612 613 data16 = (new_fw[j] << 8) | new_fw[j + 1]; 614 SOC_IF_ERROR_RETURN 615 (WRITE_PHY84740_MMF_PMA_PMD_REG 616 (unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, data16)); 617 } 618 619 /* make sure last code word is read by the micro */ 620 sal_udelay(20); 621 622 /* Read Hand-Shake message (Done) from Micro */ 623 SOC_IF_ERROR_RETURN 624 (READ_PHY84740_MMF_PMA_PMD_REG 625 (unit, pc, PHY84740_PMAD_M8051_MSGOUT_REG, &data16)); 626 627 /* Download done message */ 628 LOG_INFO(BSL_LS_SOC_PHY, 629 (BSL_META_U(unit, 630 "u=%d p=%d MDIO firmware download done message: 0x%x\n"), 631 unit, port, data16)); 632 633 /* Clear LASI status */ 634 SOC_IF_ERROR_RETURN 635 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16)); 636 637 /* Wait for LASI to be asserted when M8051 writes checksum to MSG_OUTr */ 638 sal_udelay(100); /* Wait for 100 usecs */ 639 640 SOC_IF_ERROR_RETURN 641 (READ_PHY84740_MMF_PMA_PMD_REG 642 (unit, pc, PHY84740_PMAD_M8051_MSGOUT_REG, &data16)); 643 644 /* Need to check if checksum is correct */ 645 SOC_IF_ERROR_RETURN 646 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &data16)); 647 648 if (data16 != 0x600D) { 649 /* Bad CHECKSUM */ 650 LOG_CLI((BSL_META_U(unit, 651 "MDIO Firmware downlad failure:" 652 "Incorrect Checksum %x\n"), data16)); 653 return SOC_E_FAIL; 654 } 655 656 /* read Rev-ID */ 657 SOC_IF_ERROR_RETURN 658 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1A, &data16)); 659 LOG_INFO(BSL_LS_SOC_PHY, 660 (BSL_META_U(unit, 661 "u=%d p=%d MDIO Firmware download revID: 0x%x\n"), 662 unit, port, data16)); 663 664 return SOC_E_NONE; 665 } 666 667 STATIC int _phy84740_rom_firmware_download(int unit, int port, phy_ctrl_t *pc) 668 { 669 int lane; 670 uint16 data16; 671 uint16 mask16; 672 if (PHY84740_SINGLE_PORT_MODE(pc)) { 673 for (lane = 3; lane >= 0; lane--) { 674 SOC_IF_ERROR_RETURN 675 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 676 PHY84740_PMAD_AER_ADDR_REG, 677 lane)); 678 679 /* 0xca85[3]=1, 32K download */ 680 mask16 = (1 << 3); 681 data16 = mask16; 682 SOC_IF_ERROR_RETURN 683 (MODIFY_PHY84740_MMF_PMA_PMD_REG 684 (unit, pc, 0xCA85, data16, mask16)); 685 } 686 687 /* 0xc848[15]=1, SPI-ROM downloading to RAM, 0xc848[14]=1, serial boot */ 688 mask16 = (1 << 15) | (1 << 14); 689 data16 = mask16; 690 691 /* 0xc848[13]=0, SPI-ROM downloading not done, 0xc848[2]=0, spi port enable */ 692 mask16 |= (1 << 13) | (1 << 2); 693 SOC_IF_ERROR_RETURN 694 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc848, data16, mask16)); 695 696 /* apply software reset to download code from SPI-ROM */ 697 SOC_IF_ERROR_RETURN 698 (WRITE_PHY84740_PMA_PMD_CTRLr(unit, pc, MII_CTRL_RESET)); 699 700 for (lane = 0; lane < NUM_LANES; lane++) { 701 SOC_IF_ERROR_RETURN 702 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 703 PHY84740_PMAD_AER_ADDR_REG, 704 lane)); 705 /* wait for at least 50ms */ 706 sal_usleep(100000); 707 SOC_IF_ERROR_RETURN 708 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16)); 709 LOG_INFO(BSL_LS_SOC_PHY, 710 (BSL_META_U(unit, 711 "u=%d p=%d lane%d SPI-ROM download done msg 0x%x\n"), 712 unit, port, lane, data16)); 713 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 714 (unit, pc, 0xCA1C, &data16)); 715 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 716 (unit, pc, 0xCA1A, &data16)); 717 } 718 SOC_IF_ERROR_RETURN 719 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 720 PHY84740_PMAD_AER_ADDR_REG, 0)); 721 } else { /* single lane */ 722 /* 0xca85[3]=1, 32K download */ 723 mask16 = (1 << 3); 724 data16 = mask16; 725 SOC_IF_ERROR_RETURN 726 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA85, data16, mask16)); 727 728 /* 0xc848[15]=1, SPI-ROM downloading to RAM, 0xc848[14]=1, serial boot */ 729 mask16 = (1 << 15) | (1 << 14); 730 data16 = mask16; 731 SOC_IF_ERROR_RETURN 732 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc848, data16, mask16)); 733 734 /* 0xc848[13]=0, SPI-ROM downloading not done, 0xc848[2]=0, spi port enable */ 735 mask16 = (1 << 13) | (1 << 2); 736 data16 = 0; 737 SOC_IF_ERROR_RETURN 738 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc848, data16, mask16)); 739 740 /* apply software reset to download code from SPI-ROM */ 741 SOC_IF_ERROR_RETURN 742 (MODIFY_PHY84740_PMA_PMD_CTRLr(unit, pc, 743 MII_CTRL_RESET, MII_CTRL_RESET)); 744 745 /* wait for at least 50ms */ 746 sal_usleep(100000); 747 SOC_IF_ERROR_RETURN 748 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16)); 749 LOG_INFO(BSL_LS_SOC_PHY, 750 (BSL_META_U(unit, 751 "u=%d p=%d SPI-ROM download done msg 0x%x\n"), 752 unit, port, data16)); 753 754 } 755 return SOC_E_NONE; 756 } 757 758 /* 759 * Flip the tx/rx polarities based on the configuration. 760 */ 761 STATIC int _phy_84740_polarity_flip_set(int unit, soc_port_t port) 762 { 763 int lane; 764 phy_ctrl_t *pc; 765 uint16 tx_pol, rx_pol; 766 uint16 data16, mask16; 767 768 pc = EXT_PHY_SW_STATE(unit, port); 769 770 tx_pol = 0; 771 rx_pol = 0; 772 773 /* get the reset default value. The 84740 device has the TX polarity flipped 774 * by default. Construct the init default value 775 */ 776 777 if ((PHY84740_SINGLE_PORT_MODE(pc))) { 778 for (lane = 0; lane < NUM_LANES; lane++) { 779 /* point to the each lane starting at lane0 */ 780 SOC_IF_ERROR_RETURN 781 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 782 PHY84740_PMAD_AER_ADDR_REG, 783 P2L_MAP(pc, lane))); 784 785 /* read both TX/RX polarities */ 786 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 787 (unit, pc, PHY84740_DIG_CTRL_REG, &data16)); 788 if (data16 & PHY84740_TX_POLARITY_FLIP_MASK) { 789 tx_pol |= POL_CONFIG_LANE_MASK(lane); 790 } 791 if (data16 & PHY84740_RX_POLARITY_FLIP_MASK) { 792 rx_pol |= POL_CONFIG_LANE_MASK(lane); 793 } 794 } 795 } else { /* quad mode */ 796 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 797 (unit, pc, PHY84740_DIG_CTRL_REG, &data16)); 798 if (data16 & PHY84740_TX_POLARITY_FLIP_MASK) { 799 tx_pol = POL_CONFIG_ALL_LANES; 800 } 801 if (data16 & PHY84740_RX_POLARITY_FLIP_MASK) { 802 rx_pol = POL_CONFIG_ALL_LANES; 803 } 804 } 805 806 tx_pol = soc_property_port_get(unit, port, 807 spn_PHY_PCS_TX_POLARITY_FLIP, tx_pol); 808 rx_pol = soc_property_port_get(unit, port, 809 spn_PHY_PCS_RX_POLARITY_FLIP, rx_pol); 810 811 mask16 = PHY84740_TX_POLARITY_FLIP_MASK | PHY84740_RX_POLARITY_FLIP_MASK; 812 813 if ((PHY84740_SINGLE_PORT_MODE(pc))) { 814 for (lane = 0; lane < NUM_LANES; lane++) { 815 data16 = 0; 816 817 /* point to the each lane starting at lane0 */ 818 SOC_IF_ERROR_RETURN 819 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 820 PHY84740_PMAD_AER_ADDR_REG, 821 P2L_MAP(pc, lane))); 822 823 if ((tx_pol == POL_CONFIG_ALL_LANES) || 824 ((tx_pol & POL_CONFIG_LANE_MASK(lane)) == 825 POL_CONFIG_LANE_MASK(lane))) { 826 data16 = PHY84740_TX_POLARITY_FLIP_MASK; 827 } 828 if ((rx_pol == POL_CONFIG_ALL_LANES) || 829 ((rx_pol & POL_CONFIG_LANE_MASK(lane)) == 830 POL_CONFIG_LANE_MASK(lane))) { 831 data16 |= PHY84740_RX_POLARITY_FLIP_MASK; 832 } 833 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 834 PHY84740_DIG_CTRL_REG, 835 data16, 836 mask16)); 837 } 838 /* point back to lane0 */ 839 SOC_IF_ERROR_RETURN 840 (WRITE_PHY84740_MMF_PMA_PMD_REG 841 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 842 } else { /* quad-port mode */ 843 data16 = 0; 844 tx_pol = PHY84740_10G_POL_CFG_GET(pc, tx_pol); 845 if (tx_pol) { 846 data16 = PHY84740_TX_POLARITY_FLIP_MASK; 847 } 848 rx_pol = PHY84740_10G_POL_CFG_GET(pc, rx_pol); 849 if (rx_pol) { 850 data16 |= PHY84740_RX_POLARITY_FLIP_MASK; 851 } 852 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 853 (unit, pc, PHY84740_DIG_CTRL_REG, data16, mask16)); 854 } 855 856 return SOC_E_NONE; 857 } 858 859 /* 860 * Squelch enable/disable 861 */ 862 STATIC int _phy_84740_squelch_enable(int unit, soc_port_t port, 863 int intf, int enable, int force) 864 { 865 phy_ctrl_t *pc; 866 int ix; 867 int repeater_mode; 868 uint16 data16, mask16,bit,speed_val; 869 uint32 devid; 870 871 pc = EXT_PHY_SW_STATE(unit, port); 872 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 873 (pc->unit, pc->port, pc, &devid)); 874 875 if (PHY84740_IS_QUADRA(devid)) { 876 if ((PHY_DIAG_INTF_LINE == intf || REVERSE_MODE(pc)) && 877 PHY_DIAG_INTF_SYS != intf) { 878 if(PHY84740_SINGLE_PORT_MODE(pc)) { 879 mask16 = (1 << 6); 880 data16 = enable ? mask16 : 0; 881 for (ix = 0; ix < NUM_LANES; ix++) { 882 SOC_IF_ERROR_RETURN 883 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 884 PHY84740_PMAD_AER_ADDR_REG, 885 ix)); 886 SOC_IF_ERROR_RETURN 887 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 888 0xcd18, data16, mask16)); 889 SOC_IF_ERROR_RETURN 890 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 891 0xcd16, 892 enable ? (1 << 4) : 0, 893 (1 << 4))); 894 } 895 /* point back to lane0 */ 896 SOC_IF_ERROR_RETURN 897 (WRITE_PHY84740_MMF_PMA_PMD_REG 898 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 899 900 } else {/*quad ports**/ 901 SOC_IF_ERROR_RETURN 902 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16)); 903 repeater_mode = ((data16 & 0x6) == 0x6) ? TRUE : FALSE; 904 if (repeater_mode) { 905 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 906 (unit, pc, 0xc81f, &speed_val)); 907 bit = (speed_val & (1 << 2)) ? 3 : 4; 908 mask16 = (1 << bit) | (1 << 6); 909 data16 = enable ? mask16 : 0; 910 SOC_IF_ERROR_RETURN 911 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 912 0xcd18, data16, mask16)); 913 } 914 } 915 } else { /*system side or not reverse mode*/ 916 if (PHY84740_SINGLE_PORT_MODE(pc)) { 917 mask16 = (1 << 6) | (1 << 11); 918 data16 = enable ? mask16 : 0; 919 for (ix = 0; ix < NUM_LANES; ix++) { 920 SOC_IF_ERROR_RETURN 921 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 922 PHY84740_PMAD_AER_ADDR_REG, 923 ix)); 924 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 925 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_XFI_PMA_PMD_REG(unit, 926 pc, 927 0xcd18, 928 data16, 929 mask16)); 930 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 931 } 932 /* point back to lane0 */ 933 SOC_IF_ERROR_RETURN 934 (WRITE_PHY84740_MMF_PMA_PMD_REG 935 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 936 } else {/* quad port*/ 937 SOC_IF_ERROR_RETURN 938 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16)); 939 repeater_mode = ((data16 & 0x6) == 0x6) ? TRUE : FALSE; 940 if (repeater_mode) { 941 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 942 (unit, pc, 0xc81f, &speed_val)); 943 bit = (speed_val & (1 << 2)) ? 3 : 4; 944 mask16 = (1 << bit) | (1 << 6); 945 data16 = enable ? mask16 : 0; 946 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 947 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_XFI_PMA_PMD_REG(unit, pc, 948 0xcd18, 949 data16, 950 mask16)); 951 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 952 } 953 } 954 } 955 } else { 956 if ((PHY_DIAG_INTF_LINE == intf || REVERSE_MODE(pc)) && 957 PHY_DIAG_INTF_SYS != intf) { 958 if (PHY84740_SINGLE_PORT_MODE(pc)) { 959 960 /* Note: following line needed as workaround */ 961 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 962 963 mask16 = (1 << 6); 964 data16 = enable ? mask16 : 0; 965 966 for (ix = 0; ix < NUM_LANES; ix++) { 967 SOC_IF_ERROR_RETURN 968 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 969 PHY84740_PMAD_AER_ADDR_REG, 970 ix)); 971 972 SOC_IF_ERROR_RETURN 973 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 974 0xcd18, data16, mask16)); 975 976 SOC_IF_ERROR_RETURN 977 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 978 0xcd16, 979 enable ? 980 (force ?((1 << 3)|(1 << 4)) 981 :(1 << 4)) 982 : 0, 983 (1 << 3)|(1 << 4))); 984 } 985 /* point back to lane0 */ 986 SOC_IF_ERROR_RETURN 987 (WRITE_PHY84740_MMF_PMA_PMD_REG 988 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 989 } else { 990 SOC_IF_ERROR_RETURN 991 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 992 0xcd16, 993 force ? (1 << 3) : 0, 994 (1 << 3))); 995 SOC_IF_ERROR_RETURN 996 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16)); 997 998 repeater_mode = ((data16 & 0x6) == 0x6) ? TRUE : FALSE; 999 if (repeater_mode) { 1000 mask16 = (1 << 4) | (1 << 6); 1001 data16 = enable ? mask16 : 0; 1002 1003 SOC_IF_ERROR_RETURN 1004 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 1005 0xcd18, data16, mask16)); 1006 } 1007 } 1008 1009 } else { /*system side or not reverse mode*/ 1010 if (PHY84740_SINGLE_PORT_MODE(pc)) { 1011 1012 mask16 = (1 << 6) | (1 << 11); 1013 data16 = enable ? mask16 : 0; 1014 1015 for (ix = 0; ix < NUM_LANES; ix++) { 1016 SOC_IF_ERROR_RETURN 1017 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 1018 PHY84740_PMAD_AER_ADDR_REG, 1019 ix)); 1020 1021 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 1022 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_XFI_PMA_PMD_REG(unit, 1023 pc, 1024 0xcd18, 1025 data16, 1026 mask16)); 1027 1028 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 1029 } 1030 /* point back to lane0 */ 1031 SOC_IF_ERROR_RETURN 1032 (WRITE_PHY84740_MMF_PMA_PMD_REG 1033 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 1034 } else { 1035 SOC_IF_ERROR_RETURN 1036 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16)); 1037 1038 repeater_mode = ((data16 & 0x6) == 0x6) ? TRUE : FALSE; 1039 if (repeater_mode) { 1040 mask16 = (1 << 4) | (1 << 6); 1041 data16 = enable ? mask16 : 0; 1042 1043 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 1044 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_XFI_PMA_PMD_REG(unit, pc, 1045 0xcd18, 1046 data16, 1047 mask16)); 1048 1049 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 1050 } 1051 } 1052 } 1053 } 1054 return SOC_E_NONE; 1055 } 1056 1057 STATIC int 1058 _phy_84740_firmware_is_downloaded(int unit, soc_port_t port, int ext_rom) 1059 { 1060 int rv = 0; 1061 uint16 data16; 1062 phy_ctrl_t *pc; 1063 1064 pc = EXT_PHY_SW_STATE(unit, port); 1065 1066 if (soc_property_port_get(unit, port,spn_PHY_FORCE_FIRMWARE_LOAD, TRUE)) { 1067 return 0; 1068 } 1069 1070 /* 1071 * To determine whether the firmware has been downloaded, it must 1072 * pass the following: 1073 * 1. firmware is in RAM: 1.c848.13==1 1074 * 2. expected checksum: 1.ca1c==600d 1075 * 3. version is non-zero: 1.ca1a!=0 1076 */ 1077 1078 /* 1. Firmware download status */ 1079 rv = READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC848, &data16); 1080 if (rv != SOC_E_NONE) { 1081 return 0; 1082 } 1083 if (ext_rom) { 1084 if ((data16 & 0xa000) != 0xa000) { 1085 return 0; 1086 } 1087 } else if ((data16 & 0xf000) != 0x7000) { 1088 return 0; 1089 } 1090 LOG_INFO(BSL_LS_SOC_PHY, 1091 (BSL_META_U(unit, 1092 "FW download status=%x: u=%d p=%d\n"), data16, unit, port)); 1093 1094 /* 2. Expected checksum */ 1095 rv = READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &data16); 1096 if ((rv != SOC_E_NONE) || (data16 != 0x600D)) { 1097 return 0; 1098 } 1099 LOG_INFO(BSL_LS_SOC_PHY, 1100 (BSL_META_U(unit, 1101 "FW checksum=%x: u=%d p=%d\n"), data16, unit, port)); 1102 1103 /* 3. non-zero version */ 1104 rv = READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1A, &data16); 1105 if ((rv != SOC_E_NONE) || (data16 == 0)) { 1106 return 0; 1107 } 1108 LOG_INFO(BSL_LS_SOC_PHY, 1109 (BSL_META_U(unit, 1110 "FW version=%x: u=%d p=%d\n"), data16, unit, port)); 1111 1112 return 1; 1113 } 1114 1115 /* Function: 1116 * phy_84740_init 1117 * Purpose: 1118 * Initialize 84740 phys 1119 * Parameters: 1120 * unit - StrataSwitch unit #. 1121 * port - StrataSwitch port #. 1122 * Returns: 1123 * SOC_E_NONE 1124 */ 1125 1126 STATIC int phy_84740_init(int unit, soc_port_t port) 1127 { 1128 soc_timeout_t to; 1129 int rv = SOC_E_NONE; 1130 uint16 data16, ucode_ver; 1131 uint16 chip_mode; 1132 phy_ctrl_t *pc; 1133 int ix; 1134 uint32 phy_ext_rom_boot = 0; 1135 uint16 mask16; 1136 uint32 devid; 1137 unsigned char *pdata; 1138 int data_len; 1139 uint32 l2p, l2p_map; 1140 1141 pc = EXT_PHY_SW_STATE(unit, port); 1142 LOG_INFO(BSL_LS_SOC_PHY, 1143 (BSL_META_U(unit, 1144 "PHY84740 init: u=%d p=%d desc=0x%x\n"), 1145 unit, port, PTR_TO_INT(pc + 1))); 1146 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 1147 (pc->unit, pc->port, pc, &devid)); 1148 1149 /* initialize default p2l map */ 1150 for (ix = 0; ix < NUM_LANES; ix++) { 1151 P2L_MAP(pc, ix) = ix; 1152 } 1153 1154 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) || 1155 (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) { 1156 PCS_REPEATER(pc) = FALSE; 1157 if (PHY84740_SINGLE_PORT_MODE(pc)) { 1158 /* Always set repeater flag in single port mode */ 1159 PHY_FLAGS_SET(unit, port, 1160 PHY_FLAGS_FIBER | PHY_FLAGS_C45 | PHY_FLAGS_REPEATER); 1161 } else { 1162 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER | PHY_FLAGS_C45); 1163 } 1164 1165 FCMAP_PASSTHROUGH(pc) = 1166 soc_property_port_get(unit, port, spn_PHY_FCMAP_PASSTHROUGH, 0); 1167 1168 if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) { 1169 LOG_INFO(BSL_LS_SOC_PHY, 1170 (BSL_META_U(unit, 1171 "PHY84740 init pass1: u=%d p=%d\n"), unit, port)); 1172 1173 /* check if to use the bcst mode for RAM uC download */ 1174 phy_ext_rom_boot = soc_property_port_get(unit, port, 1175 spn_PHY_EXT_ROM_BOOT, 1); 1176 1177 SKIP_FW_DLOAD(pc) = _phy_84740_firmware_is_downloaded(unit, port, 1178 phy_ext_rom_boot); 1179 1180 /* 1181 if (SKIP_FW_DLOAD(pc)) { 1182 LOG_CLI((BSL_META_U(unit, 1183 "u=%d, p=%d skipping firmware download\n"), 1184 unit, port)); 1185 } 1186 */ 1187 1188 if (!phy_ext_rom_boot) { 1189 if (!SKIP_FW_DLOAD(pc)) { 1190 pc->flags |= PHYCTRL_MDIO_BCST; 1191 } 1192 } else { 1193 /* 1194 * To enable firmware to be downloaded to ports which are out-of-order, 1195 * 1.c848.13 must be set on all ports first. The first port within the core that 1196 * has 1.c848.13 clear has control over the SPI-ROM, so later when the 1197 * firmware is actually being downloaded, that port will first clear 1.c848.13 1198 * and obtain control over the SPI-ROM. 1199 */ 1200 data16 = (1 << 15) | (1 << 14) | (1 << 13); 1201 mask16 = data16; 1202 SOC_IF_ERROR_RETURN 1203 (MODIFY_PHY84740_MMF_PMA_PMD_REG 1204 (unit, pc, 0xc848, data16, mask16)); 1205 } 1206 1207 /* configure to quad-port mode to prepare for the broadcast mode */ 1208 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG(pc->unit, pc, 1209 PHY84740_PMAD_CHIP_MODE_REG, 1210 &chip_mode)); 1211 1212 /* switch to quad-port mode if not already in */ 1213 if ((chip_mode & PHY84740_PMAD_CHIP_MODE_MASK) == 1214 PHY84740_PMAD_MODE_40G) { 1215 SOC_IF_ERROR_RETURN(_phy_84740_single_to_quad_mode 1216 (pc->unit, pc->port, pc)); 1217 LOG_INFO(BSL_LS_SOC_PHY, 1218 (BSL_META_U(unit, 1219 "PHY84740 init pass1 mode S to Q switch: u=%d p=%d\n"), 1220 unit, port)); 1221 } 1222 1223 /* indicate second pass of init is needed */ 1224 PHYCTRL_INIT_STATE_SET(pc, PHYCTRL_INIT_STATE_PASS2); 1225 return SOC_E_NONE; 1226 } 1227 } 1228 1229 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) || 1230 (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) { 1231 LOG_INFO(BSL_LS_SOC_PHY, 1232 (BSL_META_U(unit, 1233 "PHY84740 init pass2: u=%d p=%d\n"), unit, port)); 1234 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 1235 (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 1236 &chip_mode)); 1237 1238 /* check the current chip mode */ 1239 if ((chip_mode & PHY84740_PMAD_CHIP_MODE_MASK) == 1240 PHY84740_PMAD_MODE_40G) { 1241 /* 1242 * switch to configured mode(quad mode) if current chip mode is single mode 1243 * In quad mode, the supported speed modes are 10G and 1G forced, 1G autoneg. 1244 * However 1G currently is only working with QSFP fiber cable not Cu cable. 1245 */ 1246 if (!(PHY84740_SINGLE_PORT_MODE(pc))) { 1247 LOG_WARN(BSL_LS_SOC_PHY, 1248 (BSL_META_U(unit, 1249 "PHY84740 init pass2 mode switch: u=%d p=%d\n"), 1250 unit, port)); 1251 SOC_IF_ERROR_RETURN(_phy_84740_single_to_quad_mode 1252 (unit, port, NULL)); 1253 1254 } else { /* configured mode is single mode */ 1255 /* if configured mode(single mode) matches current chip mode. Make sure 1256 * it is SR4/LR4. If a optical module is plugged in when the device is 1257 * configured in CR4 mode, it may damage the optical module because of big 1258 * voltage sway in CR4 mode. For now, the device is configured in 1259 * LR4/SR4 mode by default. If a QSFP Cu is used, EDC mode should be set to 1260 * 0x55. In case there is a need to go to CR4 mode, user can use interface 1261 * set function to change to the CR4 mode. In this mode, both autoneg and 1262 * forced 40G speed is supported. 1263 */ 1264 /* config DAC mode and backplane mode for LR4/SR4 */ 1265 mask16 = 1266 PHY84740_PMAD_DAC_MODE_MASK | 1267 PHY84740_PMAD_BKPLANE_MODE_MASK; 1268 if (devid == PHY84740_ID_84064) { 1269 data16 = PHY84740_PMAD_BKPLANE_MODE_MASK; 1270 } else { 1271 data16 = 0; 1272 } 1273 1274 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 1275 (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 1276 data16, mask16)); 1277 1278 SOC_IF_ERROR_RETURN 1279 (MODIFY_PHY84740_PMA_PMD_CTRLr(unit, pc, 1280 MII_CTRL_RESET, 1281 MII_CTRL_RESET)); 1282 } 1283 } else { /* current chip mode is quad mode */ 1284 /* switch to configured mode(single mode) if current chip mode is quad mode */ 1285 if (PHY84740_SINGLE_PORT_MODE(pc)) { 1286 1287 SOC_IF_ERROR_RETURN(_phy_84740_quad_to_single_mode(unit, port)); 1288 } else { /* configured mode is quad mode */ 1289 1290 /* chip already in configured mode. config DAC/backplane mode */ 1291 mask16 = 1292 PHY84740_PMAD_DAC_MODE_MASK | 1293 PHY84740_PMAD_BKPLANE_MODE_MASK; 1294 if (devid == PHY84740_ID_84064) { 1295 data16 = PHY84740_PMAD_BKPLANE_MODE_MASK; 1296 } else { 1297 data16 = 0; 1298 } 1299 1300 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 1301 (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 1302 data16, mask16)); 1303 } 1304 } 1305 1306 /* should be done before reset */ 1307 l2p = soc_property_port_get(unit, port, spn_PHY_LANE0_L2P_MAP, 0); 1308 if (l2p >= NUM_LANES) { 1309 LOG_ERROR(BSL_LS_SOC_PHY, 1310 (BSL_META_U(unit, 1311 "PHY84740 invalid L2P lane configuration: u=%d p=%d, l2p=%d\n"), 1312 unit, port, l2p)); 1313 return SOC_E_PARAM; 1314 } 1315 1316 SINGLE_LPMODE(pc) = 1317 soc_property_port_get(unit, port, spn_PHY_TX_DISABLE_NO_LPMODE, 0); 1318 1319 /* 1320 * 1.c701 1321 * - Quebec devices specifies the physical channel number designated as 1322 * logical channel 0 1323 * - Quadra devices specifies the mapping of all physical channels to 1324 * logical channels 1325 */ 1326 data16 = 0; 1327 l2p_map = 0; 1328 if (PHY84740_IS_QUADRA(devid)) { 1329 for (ix = 0; ix < NUM_LANES; ix++) { 1330 l2p_map |= ((l2p + ix) % NUM_LANES) << (ix * 4); 1331 } 1332 data16 = l2p_map; 1333 mask16 = 0xffff; 1334 for (ix = 0; ix < NUM_LANES; ix++) { 1335 P2L_MAP(pc, ((l2p_map >> (ix * 4)) & 0xf)) = ix; 1336 } 1337 } else { 1338 data16 = l2p; 1339 mask16 = PHY84740_L2P_PHYSICAL_LANE_MASK; 1340 1341 /* physical to logical lane map, index is physical lane */ 1342 for (ix = 0; ix < NUM_LANES; ix++) { 1343 P2L_MAP(pc, (l2p + ix) % NUM_LANES) = ix; 1344 } 1345 } 1346 1347 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 1348 (unit, pc, PHY84740_PMAD_LANE0_L2P_REG, data16, 1349 mask16)); 1350 1351 /* do a soft reset */ 1352 SOC_IF_ERROR_RETURN 1353 (MODIFY_PHY84740_PMA_PMD_CTRLr(unit, pc, 1354 MII_CTRL_RESET, MII_CTRL_RESET)); 1355 1356 /* Wait for device to come out of reset */ 1357 soc_timeout_init(&to, 10000, 0); 1358 while (!soc_timeout_check(&to)) { 1359 rv = READ_PHY84740_PMA_PMD_CTRLr(unit, pc, &data16); 1360 if (((data16 & MII_CTRL_RESET) == 0) || SOC_FAILURE(rv)) { 1361 break; 1362 } 1363 } 1364 if (((data16 & MII_CTRL_RESET) != 0) || SOC_FAILURE(rv)) { 1365 LOG_WARN(BSL_LS_SOC_PHY, 1366 (BSL_META_U(unit, 1367 "PHY84740 reset failed: u=%d p=%d\n"), 1368 unit, port)); 1369 return SOC_E_FAIL; 1370 } 1371 1372 if (pc->flags & PHYCTRL_UCODE_BCST_DONE) { 1373 /* ucode is already loaded thru bcst */ 1374 1375 /* Not clearing PHYCTRL_UCODE_BCST_DONE --> 1376 This bit can be checked again, in case init is called again, 1377 to avoid an additional firmware download */ 1378 1379 phy_ext_rom_boot = 0; 1380 } else { 1381 phy_ext_rom_boot = soc_property_port_get(unit, port, 1382 spn_PHY_EXT_ROM_BOOT, 1); 1383 1384 if (SKIP_FW_DLOAD(pc)) { 1385 /* do nothing */ 1386 } else if (phy_ext_rom_boot) { 1387 SOC_IF_ERROR_RETURN 1388 (_phy84740_rom_firmware_download(unit, port, pc)); 1389 } else { /* MDIO download to RAM */ 1390 /* check if the firmware is delivered by user */ 1391 if (phy_84740_uc_firmware_hook && 1392 phy_84740_uc_firmware_hook(unit, port, devid, &pdata, 1393 &data_len)) { 1394 SOC_IF_ERROR_RETURN(_phy84740_mdio_firmware_download 1395 (unit, port, pc, pdata, data_len)); 1396 } else { 1397 if (devid == PHY84740_ID_84754) { 1398 SOC_IF_ERROR_RETURN 1399 (_phy84740_mdio_firmware_download 1400 (unit, port, pc, phy84754_ucode_bin, 1401 phy84754_ucode_bin_len)); 1402 } else if (devid == PHY84740_ID_84740) { 1403 /* do not use 84753/84754 ucode for 84740. There is a voltage differece */ 1404 SOC_IF_ERROR_RETURN 1405 (_phy84740_mdio_firmware_download 1406 (unit, port, pc, phy84740_ucode_bin, 1407 phy84740_ucode_bin_len)); 1408 } else if (devid == PHY84740_ID_84064) { 1409 SOC_IF_ERROR_RETURN 1410 (_phy84740_mdio_firmware_download 1411 (unit, port, pc, phy84064_ucode_bin, 1412 phy84064_ucode_bin_len)); 1413 } else if (devid == PHY84740_ID_84753) { 1414 SOC_IF_ERROR_RETURN 1415 (_phy84740_mdio_firmware_download 1416 (unit, port, pc, phy84753_ucode_bin, 1417 phy84753_ucode_bin_len)); 1418 } else if (devid == PHY84740_ID_84752) { 1419 SOC_IF_ERROR_RETURN 1420 (_phy84740_mdio_firmware_download 1421 (unit, port, pc, phy84752_ucode_bin, 1422 phy84752_ucode_bin_len)); 1423 } else if (devid == PHY84740_ID_84784) { 1424 SOC_IF_ERROR_RETURN 1425 (_phy84740_mdio_firmware_download 1426 (unit, port, pc, phy84784_ucode_bin, 1427 phy84784_ucode_bin_len)); 1428 } else if (devid == PHY84740_ID_84780) { 1429 SOC_IF_ERROR_RETURN 1430 (_phy84740_mdio_firmware_download 1431 (unit, port, pc, phy84780_ucode_bin, 1432 phy84780_ucode_bin_len)); 1433 } else if (devid == PHY84740_ID_84318) { 1434 SOC_IF_ERROR_RETURN 1435 (_phy84740_mdio_firmware_download(unit,port,pc,phy84318_ucode_bin, 1436 phy84318_ucode_bin_len)); 1437 } else if (PHY84740_IS_QUADRA(devid)) { 1438 SOC_IF_ERROR_RETURN 1439 (_phy84740_mdio_firmware_download 1440 (unit, port, pc, phy84758_ucode_bin, 1441 phy84758_ucode_bin_len)); 1442 } else { 1443 LOG_WARN(BSL_LS_SOC_PHY, 1444 (BSL_META_U(unit, 1445 "84740: p=%d unknown device id: 0x%x\n"), 1446 port,devid)); 1447 } 1448 } 1449 } 1450 } 1451 1452 /* reset will restart the uC. wait a few ms for checksum to be written */ 1453 sal_udelay(12000); 1454 1455 REVERSE_MODE(pc) = 1456 soc_property_port_get(unit, port, spn_PORT_PHY_MODE_REVERSE, 0); 1457 if (!SOC_WARM_BOOT(unit)) { 1458 /* Disable Tx */ 1459 SOC_IF_ERROR_RETURN(phy_84740_enable_set(unit, port, FALSE)); 1460 } 1461 1462 /* read the microcode revision */ 1463 SOC_IF_ERROR_RETURN 1464 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xce00, &ucode_ver)); 1465 1466 /* check the completion of the microcode download. */ 1467 if (PHY84740_SINGLE_PORT_MODE(pc)) { 1468 uint16 cksum[4]; 1469 int ret = SOC_E_NONE; 1470 1471 for (ix = 0; ix < NUM_LANES; ix++) { 1472 SOC_IF_ERROR_RETURN 1473 (WRITE_PHY84740_MMF_PMA_PMD_REG 1474 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, ix)); 1475 1476 /* check the completion of the microcode download. */ 1477 rv = READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, 1478 &cksum[ix]); 1479 if (cksum[ix] != 0x600D || SOC_FAILURE(rv)) { 1480 ret = SOC_E_FAIL; 1481 } 1482 } 1483 if (ret == SOC_E_FAIL) { 1484 LOG_WARN(BSL_LS_SOC_PHY, 1485 (BSL_META_U(unit, 1486 "84740: p=%d SPI-ROM load: Bad Checksum lane 0,1,2,3 (0x%x)," 1487 "(0x%x), (0x%x), (0x%x)\n"), port, cksum[0], 1488 cksum[1], cksum[2], cksum[3])); 1489 return SOC_E_FAIL; 1490 } 1491 } else { 1492 rv = READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &data16); 1493 if (data16 != 0x600D || SOC_FAILURE(rv)) { 1494 LOG_WARN(BSL_LS_SOC_PHY, 1495 (BSL_META_U(unit, 1496 "84740: p=%d SPI-ROM load: Bad Checksum (0x%x)\n"), 1497 port, data16)); 1498 return SOC_E_FAIL; 1499 } 1500 } 1501 1502 LOG_WARN(BSL_LS_SOC_PHY, 1503 (BSL_META_U(unit, 1504 "%x init u=%d port=%d rom code ver. 0x%x: %s boot\n"), 1505 devid, unit, port, ucode_ver, 1506 phy_ext_rom_boot ? "SPI-ROM" : "MDIO_TO_RAM")); 1507 1508 if (!(PHY84740_SINGLE_PORT_MODE(pc))) { 1509 /* clear 1.0xcd17 to enable the PCS */ 1510 SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 1511 PHY84740_RESET_CONTROL_REGISTER, 1512 0)); 1513 } else { 1514 /* 40G no autoneg support */ 1515 /* EDC mode for SR4/LR4 0x44, done in ucode, no need to set for CR4 */ 1516 /* disable cl72 */ 1517 SOC_IF_ERROR_RETURN 1518 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x0096, 0x0000)); 1519 /* disable AN */ 1520 SOC_IF_ERROR_RETURN 1521 (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG, 0x0)); 1522 } 1523 1524 1525 mask16 = PHY84740_RXLOS_OVERRIDE_MASK | PHY84740_MOD_ABS_OVERRIDE_MASK; 1526 data16 = 0; 1527 1528 RX_LOS(pc) = soc_property_port_get(unit, port, spn_PHY_RX_LOS, 0); 1529 MOD_ABS(pc) = soc_property_port_get(unit, port, spn_PHY_MOD_ABS, 0); 1530 RX_LOS_INVERT(pc) = 1531 soc_property_port_get(unit, port, spn_PHY_RX_LOS_INVERT, 0); 1532 MOD_ABS_INVERT(pc) = 1533 soc_property_port_get(unit, port, spn_PHY_MOD_ABS_INVERT, 0); 1534 MOD_AUTO_DETECT(pc) = 1535 soc_property_port_get(unit, port, spn_PHY_MOD_AUTO_DETECT, 0); 1536 1537 /* default: override RX_LOS signalling */ 1538 if (!RX_LOS(pc)) { 1539 data16 |= PHY84740_RXLOS_OVERRIDE_MASK; 1540 } 1541 /* default: override MOD_ABS signalling */ 1542 if (!MOD_ABS(pc)) { 1543 data16 |= PHY84740_MOD_ABS_OVERRIDE_MASK; 1544 } 1545 1546 if (PHY84740_SINGLE_PORT_MODE(pc)) { 1547 for (ix = 0; ix < NUM_LANES; ix++) { 1548 SOC_IF_ERROR_RETURN 1549 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 1550 PHY84740_PMAD_AER_ADDR_REG, 1551 ix)); 1552 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 1553 (unit, pc, PHY84740_PMAD_OPTICAL_CFG_REG, 1554 data16, mask16)); 1555 } 1556 } else { 1557 SOC_IF_ERROR_RETURN 1558 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 1559 PHY84740_PMAD_OPTICAL_CFG_REG, 1560 data16, mask16)); 1561 } 1562 1563 mask16 = PHY84740_RXLOS_LVL_MASK | PHY84740_MOD_ABS_LVL_MASK; 1564 data16 = 0; 1565 /* default: RX_LOS level high */ 1566 if (!RX_LOS_INVERT(pc)) { 1567 data16 |= PHY84740_RXLOS_LVL_MASK; 1568 } 1569 /* default: MOD_ABS level high */ 1570 if (!MOD_ABS_INVERT(pc)) { 1571 data16 |= PHY84740_MOD_ABS_LVL_MASK; 1572 } 1573 1574 if (PHY84740_SINGLE_PORT_MODE(pc)) { 1575 for (ix = 0; ix < NUM_LANES; ix++) { 1576 SOC_IF_ERROR_RETURN 1577 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 1578 PHY84740_PMAD_AER_ADDR_REG, 1579 ix)); 1580 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 1581 (unit, pc, 1582 PHY84740_PMAD_OPTICAL_SIG_LVL_REG, data16, 1583 mask16)); 1584 } 1585 /* point back to lane0 */ 1586 SOC_IF_ERROR_RETURN 1587 (WRITE_PHY84740_MMF_PMA_PMD_REG 1588 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 1589 } else { 1590 SOC_IF_ERROR_RETURN 1591 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 1592 PHY84740_PMAD_OPTICAL_SIG_LVL_REG, 1593 data16, mask16)); 1594 } 1595 1596 if (soc_property_port_get(unit, port, spn_PHY_PCS_REPEATER, 0)) { 1597 if (!PHY84740_SINGLE_PORT_MODE(pc)) { 1598 /* put device in repeat mode. Single port is already in repeat mode */ 1599 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 1600 (unit, pc, 0xc806, 0x6, 0x6)); 1601 /* in repeater mode, 84740 will use autoneg from internal serdes. But 1602 * 84064 will still use cl73/cl72 from ifself. 1603 */ 1604 if (devid != PHY84740_ID_84064) { 1605 PCS_REPEATER(pc) = TRUE; 1606 PHY_FLAGS_SET(unit, port, 1607 PHY_FLAGS_FIBER | PHY_FLAGS_C45 | 1608 PHY_FLAGS_REPEATER); 1609 } 1610 } 1611 } 1612 1613 SOC_IF_ERROR_RETURN(_phy_84740_squelch_enable(unit, port, -1, TRUE, FALSE)); 1614 1615 if (FCMAP_PASSTHROUGH(pc)) { 1616 if ((!PHY84740_SINGLE_PORT_MODE(pc)) && (PHY84740_IS_QUADRA(devid))) { 1617 /* put device in the fcmap passthrough mode. */ 1618 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 1619 (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 0x3, 1620 0x3)); 1621 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_PMA_PMD_CTRLr 1622 (unit, pc, MII_CTRL_RESET, MII_CTRL_RESET)); 1623 } else { 1624 FCMAP_PASSTHROUGH(pc) = FALSE; 1625 } 1626 } 1627 1628 /* Polarity configuration */ 1629 SOC_IF_ERROR_RETURN(_phy_84740_polarity_flip_set(unit, port)); 1630 1631 /* check if module auto detect enabled */ 1632 if (MOD_AUTO_DETECT(pc)) { 1633 if ((ucode_ver & 0x0fff) < 0x105) { 1634 LOG_ERROR(BSL_LS_SOC_PHY, 1635 (BSL_META_U(unit, 1636 "84740 module auto detect requires ucode ver 0x105 or newer: " 1637 "u=%d p%d\n"), unit, port)); 1638 } else if (!(RX_LOS(pc) && MOD_ABS(pc))) { 1639 MOD_AUTO_DETECT(pc) = 0; 1640 LOG_ERROR(BSL_LS_SOC_PHY, 1641 (BSL_META_U(unit, 1642 "84740 module auto detect requires mod_abs and rx_lost " 1643 "to be configured: u=%d p%d\n"), unit, port)); 1644 } else if (PHY84740_SINGLE_PORT_MODE(pc)) { 1645 LOG_INFO(BSL_LS_SOC_PHY, 1646 (BSL_META_U(unit, 1647 "PHY84740 QSFP module auto detect enabled: u=%d p=%d\n"), 1648 unit, port)); 1649 rv = MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 1650 PHY84740_PMAD_GEN_PURPOSE_REG, 1651 PHY84740_PMAD_GEN_PURPOSE_MOD_AUTO_DETECT_EN, 1652 PHY84740_PMAD_GEN_PURPOSE_MOD_AUTO_DETECT_EN); 1653 if (SOC_FAILURE(rv)) { 1654 LOG_ERROR(BSL_LS_SOC_PHY, 1655 (BSL_META_U(unit, 1656 "PHY84740 setting QSP module auto detect failed: u=%d p%d\n"), 1657 unit, port)); 1658 } else { 1659 MOD_AUTO_DETECT_MSG(pc) = 1; 1660 } 1661 } else if (devid == PHY84740_ID_84754) { 1662 LOG_INFO(BSL_LS_SOC_PHY, 1663 (BSL_META_U(unit, 1664 "PHY84740 SFP module auto detect on: u=%d p=%d\n"), 1665 unit, port)); 1666 rv = MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 1667 PHY84740_MOD_AUTO_DETECT_STS_REG, 1668 PHY84740_MOD_AUTO_DETECT_STS_SFP_EN, 1669 PHY84740_MOD_AUTO_DETECT_STS_SFP_EN); 1670 if (SOC_FAILURE(rv)) { 1671 LOG_ERROR(BSL_LS_SOC_PHY, 1672 (BSL_META_U(unit, 1673 "PHY84740 setting SFP module auto detect failed: u=%d p%d\n"), 1674 unit, port)); 1675 } else { 1676 MOD_AUTO_DETECT_MSG(pc) = 1; 1677 } 1678 } else { 1679 LOG_ERROR(BSL_LS_SOC_PHY, 1680 (BSL_META_U(unit, 1681 "PHY84740 module auto detect not supported: u=%d p%d\n"), 1682 unit, port)); 1683 } 1684 } 1685 } 1686 1687 if (PHY84740_IS_QUADRA_BACKPLANE(devid)) { 1688 mask16 = PHY84740_PMAD_DAC_MODE_MASK | PHY84740_PMAD_BKPLANE_MODE_MASK; 1689 data16 = PHY84740_PMAD_BKPLANE_MODE_MASK; 1690 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 1691 (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, data16, 1692 mask16)); 1693 } 1694 return SOC_E_NONE; 1695 } 1696 1697 /* 1698 * Function: 1699 * phy_84740_an_get 1700 * Purpose: 1701 * Get the current auto-negotiation status (enabled/busy) 1702 * Parameters: 1703 * unit - StrataSwitch unit #. 1704 * port - StrataSwitch port #. 1705 * an - (OUT) if true, auto-negotiation is enabled. 1706 * an_done - (OUT) if true, auto-negotiation is complete. This 1707 * value is undefined if an == false. 1708 * Returns: 1709 * SOC_E_XXX 1710 */ 1711 1712 STATIC int phy_84740_an_get(int unit, soc_port_t port, int *an, int *an_done) 1713 { 1714 phy_ctrl_t *pc; 1715 uint16 an_status; 1716 uint32 devid; 1717 1718 pc = EXT_PHY_SW_STATE(unit, port); 1719 1720 if (FCMAP_PASSTHROUGH(pc)) { 1721 *an = TRUE; 1722 *an_done = TRUE; 1723 return SOC_E_NONE; 1724 } 1725 1726 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 1727 (unit, pc, PHY84740_PMAD_INTR_VALUE_REG, &an_status)); 1728 *an_done = (an_status & PHY84740_AUTONEG_COMPLETE) ? TRUE : FALSE; 1729 1730 if (PHY84740_SINGLE_PORT_MODE(pc)) { 1731 SOC_IF_ERROR_RETURN 1732 (READ_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG, &an_status)); 1733 *an = (an_status & PHY84740_AN_ENABLE) ? TRUE : FALSE; 1734 } else { 1735 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 1736 (pc->unit, pc->port, pc, &devid)); 1737 if (PHY84740_IS_QUADRA_BACKPLANE(devid)) { 1738 SOC_IF_ERROR_RETURN 1739 (READ_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG, &an_status)); 1740 1741 } else { 1742 SOC_IF_ERROR_RETURN 1743 (READ_PHY84740_MMF_AN_REG(unit, pc, 0xFFE0, &an_status)); 1744 } 1745 *an = (an_status & PHY84740_AN_ENABLE) ? TRUE : FALSE; 1746 1747 /* Confirmed value from 7.0x8309[5] */ 1748 if (*an == FALSE) { 1749 SOC_IF_ERROR_RETURN 1750 (READ_PHY84740_MMF_AN_REG(unit, pc, 0x8309, &an_status)); 1751 *an = (an_status & (1 << 5)) ? FALSE : TRUE ; 1752 } 1753 } 1754 return SOC_E_NONE; 1755 } 1756 1757 /* 1758 * Function: 1759 * phy_84740_an_set 1760 * Purpose: 1761 * Enable or disabled auto-negotiation on the specified port. 1762 * Parameters: 1763 * unit - StrataSwitch unit #. 1764 * port - StrataSwitch port #. 1765 * an - Boolean, if true, auto-negotiation is enabled 1766 * (and/or restarted). If false, autonegotiation is disabled. 1767 * Returns: 1768 * SOC_E_XXX 1769 */ 1770 STATIC int phy_84740_an_set(int unit, soc_port_t port, int an) 1771 { 1772 phy_ctrl_t *pc; 1773 phy_ctrl_t *int_pc; 1774 uint16 mode = 0; 1775 uint32 devid = 0; 1776 1777 pc = EXT_PHY_SW_STATE(unit, port); 1778 1779 LOG_INFO(BSL_LS_SOC_PHY, 1780 (BSL_META_U(unit, 1781 "phy_84740_an_set: u=%d p=%d an=%d\n"), 1782 unit, port, an)); 1783 /* make sure internal autoneg is turned off always */ 1784 int_pc = INT_PHY_SW_STATE(unit, port); 1785 1786 if (FCMAP_PASSTHROUGH(pc)) { 1787 if (NULL != int_pc) { 1788 SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_SET 1789 (int_pc->pd, unit, port, FALSE)); 1790 } 1791 return SOC_E_NONE; 1792 } 1793 1794 if (REVERSE_MODE(pc) && IS_HG_PORT(unit, port)) { 1795 /* Both WC and external phy need to set AN off @ 10G or 40G */ 1796 an = 0; 1797 if (NULL != int_pc) { 1798 if (PHY84740_SINGLE_PORT_MODE(pc)) { 1799 /* 1800 * Internal Serdes needs to be in forced KR4 (a misnomer), meaning 1801 * DFE is enabled but cl73 (or cl37) are turned off. This enables 1802 * the equalizer as required for KR backplane interfaces 1803 */ 1804 SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_SET 1805 (int_pc->pd, unit, port, 0)); 1806 SOC_IF_ERROR_RETURN(PHY_INTERFACE_SET 1807 (int_pc->pd, unit, port, SOC_PORT_IF_KR4)); 1808 SOC_IF_ERROR_RETURN(PHY_SPEED_SET 1809 (int_pc->pd, unit, port, 40000)); 1810 1811 /* disable cl72: 1.96=0 (device 1, register 0x96) */ 1812 SOC_IF_ERROR_RETURN 1813 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x0096, 0)); 1814 /* disable AN: 7.0=0 (device 7, register 0) */ 1815 SOC_IF_ERROR_RETURN 1816 (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG, 0)); 1817 } 1818 } 1819 } 1820 1821 if (NULL != int_pc) { 1822 if (REVERSE_MODE(pc)) { 1823 SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_SET 1824 (int_pc->pd, unit, port, an)); 1825 } else { 1826 /* if in passthru mode, enable autoneg on internal serdes */ 1827 if (PCS_REPEATER(pc)) { 1828 SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_SET 1829 (int_pc->pd, unit, port, an)); 1830 } else { 1831 SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_SET 1832 (int_pc->pd, unit, port, FALSE)); 1833 } 1834 } 1835 } 1836 1837 /* 0xc700(0xc710 once firmware fixed), PCS link status overide for CR4 autoneg. 1838 * bit 4 enable override, bit 1 status indication 1839 * system side link status check in 40G 0xcd04, this is per lane register 1840 */ 1841 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 1842 (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, &mode)); 1843 1844 if (PHY84740_SINGLE_PORT_MODE(pc)) { 1845 /* make sure internal speed is set to 40G */ 1846 if (an) { 1847 if (NULL != int_pc) { 1848 if (!REVERSE_MODE(pc)) { 1849 if (soc_property_port_get(unit, port, spn_PHY_LONG_XFI, 0)) { 1850 PHY_INTERFACE_SET(int_pc->pd, unit, port, 1851 SOC_PORT_IF_CR); 1852 } 1853 SOC_IF_ERROR_RETURN(PHY_SPEED_SET 1854 (int_pc->pd, unit, port, 40000)); 1855 } 1856 } 1857 } 1858 1859 /* autoneg only supported in CR4 mode */ 1860 /* no autoneg if in SR4/LR4 mode */ 1861 if (!(mode & 1862 (PHY84740_PMAD_DAC_MODE_MASK | 1863 PHY84740_PMAD_BKPLANE_MODE_MASK)) || 1864 (REVERSE_MODE(pc) && IS_HG_PORT(unit, port))) { 1865 an = 0; 1866 } 1867 1868 /* enable/disable cl72 */ 1869 SOC_IF_ERROR_RETURN 1870 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x0096, an ? 2 : 0)); 1871 /* enable/disable AN */ 1872 SOC_IF_ERROR_RETURN 1873 (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG, 1874 an ? AN_ENABLE | AN_RESTART : 0x0)); 1875 1876 return SOC_E_NONE; 1877 } else { /* quad mode, cl73 for backplane */ 1878 if (mode & PHY84740_PMAD_BKPLANE_MODE_MASK) { 1879 /* make sure internal speed is set to 10G */ 1880 if (an) { 1881 if (NULL != int_pc) { 1882 if (soc_property_port_get(unit, port, spn_PHY_LONG_XFI, 0)) { 1883 PHY_INTERFACE_SET(int_pc->pd, unit, port, 1884 SOC_PORT_IF_CR); 1885 } 1886 SOC_IF_ERROR_RETURN(PHY_SPEED_SET 1887 (int_pc->pd, unit, port, 10000)); 1888 } 1889 } 1890 1891 /* enable/disable cl72 */ 1892 SOC_IF_ERROR_RETURN 1893 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x0096, an ? 2 : 0)); 1894 /* enable/disable AN */ 1895 SOC_IF_ERROR_RETURN 1896 (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG, 1897 an ? AN_ENABLE | AN_RESTART : 0x0)); 1898 } 1899 } 1900 1901 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 1902 (pc->unit, pc->port, pc, &devid)); 1903 1904 if (an) { 1905 /* Enable Clause 37 AN */ 1906 if (!(PHY84740_IS_QUADRA_BACKPLANE(devid))) { 1907 SOC_IF_ERROR_RETURN 1908 (WRITE_PHY84740_MMF_AN_REG 1909 (unit, pc, 0xFFE0, MII_CTRL_AE | MII_CTRL_RAN)); 1910 } 1911 SOC_IF_ERROR_RETURN 1912 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x8309, 0, (1 << 5))); 1913 } else { 1914 /* disable Clause 37 AN */ 1915 if (!(PHY84740_IS_QUADRA_BACKPLANE(devid))) { 1916 SOC_IF_ERROR_RETURN 1917 (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0xFFE0, 0x0)); 1918 } 1919 /* Enable encoded forced speed derived from ieeeControl1 and ieeeControl2 */ 1920 SOC_IF_ERROR_RETURN 1921 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x8309, (1 << 5), (1 << 5))); 1922 } 1923 1924 return SOC_E_NONE; 1925 } 1926 1927 /* 1928 * Function: 1929 * phy_84740_ability_advert_get 1930 * Purpose: 1931 * Get the current advertisement for auto-negotiation. 1932 * Parameters: 1933 * unit - StrataSwitch unit #. 1934 * port - StrataSwitch port #. 1935 * mode - (OUT) Port mode mask indicating supported options/speeds. 1936 * Returns: 1937 * SOC_E_XXX 1938 * Notes: 1939 * The advertisement is retrieved for the ACTIVE medium. 1940 * No synchronization performed at this level. 1941 */ 1942 1943 STATIC int 1944 phy_84740_ability_advert_get(int unit, soc_port_t port, 1945 soc_port_ability_t *ability) 1946 { 1947 uint16 an_adv; 1948 soc_port_mode_t mode; 1949 phy_ctrl_t *pc; 1950 1951 if (NULL == ability) { 1952 return (SOC_E_PARAM); 1953 } 1954 pc = EXT_PHY_SW_STATE(unit, port); 1955 1956 if (FCMAP_PASSTHROUGH(pc)) { 1957 ability->speed_full_duplex = SOC_PA_SPEED_10GB; 1958 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 1959 return SOC_E_NONE; 1960 } 1961 1962 if (PCS_REPEATER(pc)) { 1963 phy_ctrl_t *int_pc = INT_PHY_SW_STATE(unit, port); 1964 if (NULL != int_pc) { 1965 SOC_IF_ERROR_RETURN(PHY_ABILITY_ADVERT_GET 1966 (int_pc->pd, unit, port, ability)); 1967 } 1968 return SOC_E_NONE; 1969 } 1970 1971 mode = 0; 1972 ability->pause = 0; 1973 if (PHY84740_SINGLE_PORT_MODE(pc)) { 1974 /* advert register 1 */ 1975 SOC_IF_ERROR_RETURN 1976 (READ_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_1_REG, &an_adv)); 1977 1978 mode |= (an_adv & AN_ADVERT_40GCR4) ? SOC_PA_SPEED_40GB : 0; 1979 mode |= (an_adv & AN_ADVERT_40GKR4) ? SOC_PA_SPEED_40GB : 0; 1980 mode |= (an_adv & AN_ADVERT_10GKR) ? SOC_PA_SPEED_10GB : 0; 1981 mode |= (an_adv & AN_ADVERT_1GKX) ? SOC_PA_SPEED_1000MB : 0; 1982 ability->speed_full_duplex = mode; 1983 1984 SOC_IF_ERROR_RETURN 1985 (READ_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_0_REG, &an_adv)); 1986 1987 switch (an_adv & (AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM)) { 1988 case AN_ADVERT_PAUSE: 1989 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 1990 break; 1991 case AN_ADVERT_PAUSE_ASYM: 1992 ability->pause = SOC_PA_PAUSE_TX; 1993 break; 1994 case AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM: 1995 ability->pause = SOC_PA_PAUSE_RX; 1996 break; 1997 } 1998 } else { 1999 /* check Full Duplex advertisement on Clause 37 */ 2000 SOC_IF_ERROR_RETURN 2001 (READ_PHY84740_MMF_AN_REG(unit, pc, 0xFFE4, &an_adv)); 2002 mode |= (an_adv & MII_ANA_C37_FD) ? SOC_PA_SPEED_1000MB : 0; 2003 2004 ability->speed_full_duplex = mode; 2005 2006 switch (an_adv & (MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE)) { 2007 case MII_ANA_C37_PAUSE: 2008 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 2009 break; 2010 case MII_ANA_C37_ASYM_PAUSE: 2011 ability->pause = SOC_PA_PAUSE_TX; 2012 break; 2013 case MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE: 2014 ability->pause = SOC_PA_PAUSE_RX; 2015 break; 2016 } 2017 } 2018 2019 LOG_INFO(BSL_LS_SOC_PHY, 2020 (BSL_META_U(unit, 2021 "phy_84740_ability_advert_get: u=%d p=%d speed(FD)=0x%x pause=0x%x\n"), 2022 unit, port, ability->speed_full_duplex, ability->pause)); 2023 return SOC_E_NONE; 2024 } 2025 2026 /* 2027 * Function: 2028 * phy_84740_ability_remote_get 2029 * Purpose: 2030 * Get the device's complete abilities. 2031 * Parameters: 2032 * unit - StrataSwitch unit #. 2033 * port - StrataSwitch port #. 2034 * ability - return device's abilities. 2035 * Returns: 2036 * SOC_E_XXX 2037 */ 2038 2039 STATIC int 2040 phy_84740_ability_remote_get(int unit, soc_port_t port, 2041 soc_port_ability_t *ability) 2042 { 2043 phy_ctrl_t *pc; 2044 uint16 lp_abil; 2045 2046 if (NULL == ability) { 2047 return SOC_E_PARAM; 2048 } 2049 2050 pc = EXT_PHY_SW_STATE(unit, port); 2051 2052 if (FCMAP_PASSTHROUGH(pc)) { 2053 ability->speed_full_duplex = SOC_PA_SPEED_10GB; 2054 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 2055 return SOC_E_NONE; 2056 } 2057 2058 if (PCS_REPEATER(pc)) { 2059 phy_ctrl_t *int_pc = INT_PHY_SW_STATE(unit, port); 2060 if (NULL != int_pc) { 2061 SOC_IF_ERROR_RETURN(PHY_ABILITY_REMOTE_GET 2062 (int_pc->pd, unit, port, ability)); 2063 } 2064 return SOC_E_NONE; 2065 } 2066 2067 ability->speed_half_duplex = SOC_PA_ABILITY_NONE; 2068 2069 /* check CL73 first */ 2070 SOC_IF_ERROR_RETURN 2071 (READ_PHY84740_MMF_AN_REG(unit, pc, AN_LP_ABILITY_1_REG, &lp_abil)); 2072 ability->speed_full_duplex = 2073 (lp_abil & AN_ADVERT_40GCR4) ? SOC_PA_SPEED_40GB : 0; 2074 ability->speed_full_duplex |= 2075 (lp_abil & AN_ADVERT_40GKR4) ? SOC_PA_SPEED_40GB : 0; 2076 ability->speed_full_duplex |= 2077 (lp_abil & AN_ADVERT_10GKR) ? SOC_PA_SPEED_10GB : 0; 2078 ability->speed_full_duplex |= 2079 (lp_abil & AN_ADVERT_1GKX) ? SOC_PA_SPEED_1000MB : 0; 2080 2081 SOC_IF_ERROR_RETURN 2082 (READ_PHY84740_MMF_AN_REG(unit, pc, AN_LP_ABILITY_0_REG, &lp_abil)); 2083 2084 ability->pause = 0; 2085 switch (lp_abil & (AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM)) { 2086 case AN_ADVERT_PAUSE: 2087 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 2088 break; 2089 case AN_ADVERT_PAUSE_ASYM: 2090 ability->pause = SOC_PA_PAUSE_TX; 2091 break; 2092 case AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM: 2093 ability->pause = SOC_PA_PAUSE_RX; 2094 break; 2095 } 2096 2097 /* check CL37 */ 2098 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_AN_REG(unit, pc, 0xFFE5, &lp_abil)); 2099 ability->speed_full_duplex |= (lp_abil & MII_ANA_C37_FD) ? 2100 SOC_PA_SPEED_1000MB : 0; 2101 2102 switch (lp_abil & (MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE)) { 2103 case MII_ANP_C37_PAUSE: 2104 ability->pause |= SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 2105 break; 2106 case MII_ANP_C37_ASYM_PAUSE: 2107 ability->pause |= SOC_PA_PAUSE_TX; 2108 break; 2109 case MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE: 2110 ability->pause |= SOC_PA_PAUSE_RX; 2111 break; 2112 } 2113 2114 LOG_INFO(BSL_LS_SOC_PHY, 2115 (BSL_META_U(unit, 2116 "phy_84740_ability_remote_get: u=%d p=%d speed(FD)=0x%x pause=0x%x\n"), 2117 unit, port, ability->speed_full_duplex, ability->pause)); 2118 2119 return (SOC_E_NONE); 2120 } 2121 2122 /* 2123 * Function: 2124 * phy_84740_ability_advert_set 2125 * Purpose: 2126 * Set the current advertisement for auto-negotiation. 2127 * Parameters: 2128 * unit - StrataSwitch unit #. 2129 * port - StrataSwitch port #. 2130 * mode - Port mode mask indicating supported options/speeds. 2131 * Returns: 2132 * SOC_E_XXX 2133 * Notes: 2134 * The advertisement is set only for the ACTIVE medium. 2135 * No synchronization performed at this level. 2136 */ 2137 2138 STATIC int 2139 phy_84740_ability_advert_set(int unit, soc_port_t port, 2140 soc_port_ability_t *ability) 2141 { 2142 uint16 an_adv, an_adv_cl37, mode; 2143 phy_ctrl_t *pc; 2144 2145 if (NULL == ability) { 2146 return (SOC_E_PARAM); 2147 } 2148 2149 pc = EXT_PHY_SW_STATE(unit, port); 2150 2151 if (FCMAP_PASSTHROUGH(pc)) { 2152 return SOC_E_NONE; 2153 } 2154 2155 if (PCS_REPEATER(pc)) { 2156 phy_ctrl_t *int_pc = INT_PHY_SW_STATE(unit, port); 2157 if (NULL != int_pc) { 2158 SOC_IF_ERROR_RETURN(PHY_ABILITY_ADVERT_SET 2159 (int_pc->pd, unit, port, ability)); 2160 } 2161 return SOC_E_NONE; 2162 } 2163 2164 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 2165 (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, &mode)); 2166 2167 if (PHY84740_SINGLE_PORT_MODE(pc)) { 2168 if (mode & PHY84740_PMAD_BKPLANE_MODE_MASK) { 2169 an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_40GB) ? 2170 AN_ADVERT_40GKR4 : 0; 2171 an_adv |= (ability->speed_full_duplex & SOC_PA_SPEED_10GB) ? 2172 AN_ADVERT_10GKR : 0; 2173 } else { 2174 2175 /* only advertise 40G CR4 */ 2176 an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_40GB) ? 2177 AN_ADVERT_40GCR4 : 0; 2178 } 2179 2180 /* CL73 advert register 1 */ 2181 SOC_IF_ERROR_RETURN 2182 (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_1_REG, an_adv)); 2183 2184 } else { /* quad-port mode */ 2185 if (mode & PHY84740_PMAD_BKPLANE_MODE_MASK) { 2186 an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_10GB) ? 2187 AN_ADVERT_10GKR : 0; 2188 an_adv |= (ability->speed_full_duplex & SOC_PA_SPEED_1000MB) ? 2189 AN_ADVERT_1GKX : 0; 2190 2191 /* CL73 advert register 1 */ 2192 SOC_IF_ERROR_RETURN 2193 (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_1_REG, an_adv)); 2194 } 2195 2196 /* only 1G CL37 autoneg */ 2197 an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_1000MB) ? 2198 AN_ADVERT_1G : 0; 2199 2200 /* write Full Duplex advertisement on Clause 37 */ 2201 SOC_IF_ERROR_RETURN 2202 (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0xFFE4, an_adv)); 2203 } 2204 2205 an_adv = an_adv_cl37 = 0; 2206 switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) { 2207 case SOC_PA_PAUSE_TX: 2208 an_adv = AN_ADVERT_PAUSE_ASYM; 2209 an_adv_cl37 = MII_ANA_C37_ASYM_PAUSE; 2210 break; 2211 case SOC_PA_PAUSE_RX: 2212 an_adv = AN_ADVERT_PAUSE_ASYM | AN_ADVERT_PAUSE; 2213 an_adv_cl37 = MII_ANA_C37_ASYM_PAUSE | MII_ANA_C37_PAUSE; 2214 break; 2215 case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX: 2216 an_adv_cl37 = MII_ANA_C37_PAUSE; 2217 an_adv = AN_ADVERT_PAUSE; 2218 break; 2219 } 2220 if (PHY84740_SINGLE_PORT_MODE(pc)) { 2221 SOC_IF_ERROR_RETURN 2222 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_0_REG, an_adv, 2223 AN_ADVERT_PAUSE | 2224 AN_ADVERT_PAUSE_ASYM)); 2225 } else { 2226 if (mode & PHY84740_PMAD_BKPLANE_MODE_MASK) { 2227 SOC_IF_ERROR_RETURN 2228 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_0_REG, an_adv, 2229 AN_ADVERT_PAUSE | 2230 AN_ADVERT_PAUSE_ASYM)); 2231 } 2232 2233 /* write Pause advertisement on Clause 37 */ 2234 SOC_IF_ERROR_RETURN 2235 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0xFFE4, an_adv_cl37, 2236 MII_ANA_C37_ASYM_PAUSE | 2237 MII_ANA_C37_PAUSE)); 2238 } 2239 2240 LOG_INFO(BSL_LS_SOC_PHY, 2241 (BSL_META_U(unit, 2242 "phy_8072_ability_advert_set: u=%d p=%d pause=0x%08x adv_reg1=0x%04x\n"), 2243 unit, port, ability->pause, an_adv)); 2244 2245 return SOC_E_NONE; 2246 } 2247 2248 /* 2249 * Function: 2250 * phy_84740_ability_local_get 2251 * Purpose: 2252 * Get the device's complete abilities. 2253 * Parameters: 2254 * unit - StrataSwitch unit #. 2255 * port - StrataSwitch port #. 2256 * ability - return device's abilities. 2257 * Returns: 2258 * SOC_E_XXX 2259 */ 2260 2261 STATIC int 2262 phy_84740_ability_local_get(int unit, soc_port_t port, 2263 soc_port_ability_t *ability) 2264 { 2265 phy_ctrl_t *pc; 2266 phy_ctrl_t *int_pc; 2267 uint32 pa_speed = 0; 2268 2269 pc = EXT_PHY_SW_STATE(unit, port); 2270 int_pc = INT_PHY_SW_STATE(unit, port); 2271 2272 LOG_INFO(BSL_LS_SOC_PHY, 2273 (BSL_META_U(unit, 2274 "phy_84740_ability_local_get: u=%d p=%d\n"), 2275 unit, port)); 2276 2277 if (NULL == ability) { 2278 return SOC_E_PARAM; 2279 } 2280 2281 if (FCMAP_PASSTHROUGH(pc)) { 2282 ability->speed_full_duplex = SOC_PA_SPEED_10GB; 2283 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 2284 return SOC_E_NONE; 2285 } 2286 2287 if (NULL != int_pc && PCS_REPEATER(pc)) { 2288 SOC_IF_ERROR_RETURN(PHY_ABILITY_LOCAL_GET 2289 (int_pc->pd, unit, port, ability)); 2290 return SOC_E_NONE; 2291 } 2292 ability->speed_half_duplex = SOC_PA_ABILITY_NONE; 2293 2294 pa_speed = PHY84740_SINGLE_PORT_MODE(pc) ? SOC_PA_SPEED_40GB : 2295 SOC_PA_SPEED_10GB | SOC_PA_SPEED_1000MB; 2296 ability->speed_full_duplex = pa_speed; 2297 2298 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 2299 ability->interface = SOC_PA_INTF_XGMII; 2300 ability->medium = SOC_PA_MEDIUM_FIBER; 2301 ability->loopback = SOC_PA_LB_PHY; 2302 ability->flags = SOC_PA_AUTONEG; 2303 2304 LOG_INFO(BSL_LS_SOC_PHY, 2305 (BSL_META_U(unit, 2306 "phy_84740_ability_local_get: u=%d p=%d speed=0x%x\n"), 2307 unit, port, ability->speed_full_duplex)); 2308 2309 return (SOC_E_NONE); 2310 } 2311 2312 STATIC int _phy84740_mod_auto_detect_update(int unit, soc_port_t port) 2313 { 2314 phy_ctrl_t *pc; 2315 uint16 data; 2316 uint16 status; 2317 2318 pc = EXT_PHY_SW_STATE(unit, port); 2319 2320 if (PHY84740_SINGLE_PORT_MODE(pc)) { 2321 /* point to lane 0 */ 2322 SOC_IF_ERROR_RETURN 2323 (WRITE_PHY84740_MMF_PMA_PMD_REG 2324 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 2325 } 2326 2327 /* check for presence */ 2328 SOC_IF_ERROR_RETURN 2329 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 2330 PHY84740_PMAD_OPTICAL_CFG_REG, &data)); 2331 if (data & PHY84740_PMAD_OPTICAL_CFG_MOD_PRESENCE) { 2332 SOC_IF_ERROR_RETURN 2333 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 2334 PHY84740_MOD_AUTO_DETECT_STS_REG, 2335 &status)); 2336 /* make sure auto detection completed */ 2337 if (!(status & PHY84740_MOD_AUTO_DETECT_STS_NOT_DONE)) { 2338 if (MOD_AUTO_DETECT_MSG(pc)) { 2339 /* present and must print message */ 2340 MOD_AUTO_DETECT_MSG(pc) = 0; 2341 if (status & PHY84740_MOD_AUTO_DETECT_STS_NOT_RES) { 2342 uint16 mod_130 = 0, mod_131 = 0; 2343 (void)(READ_PHY84740_MMF_PMA_PMD_REG 2344 (unit, pc, 0x81f2, &mod_130)); 2345 (void)(READ_PHY84740_MMF_PMA_PMD_REG 2346 (unit, pc, 0x81f3, &mod_131)); 2347 LOG_ERROR(BSL_LS_SOC_PHY, 2348 (BSL_META_U(unit, 2349 "PHY84740 could not detect module, " 2350 "defaulting to SR(4): u=%d p=%d sts=0x%x (0x%x:0x%x)\n"), 2351 unit, port, status, mod_130, mod_131)); 2352 } else { 2353 /* auto detect done and successfully resolved */ 2354 SOC_IF_ERROR_RETURN 2355 (READ_PHY84740_MMF_PMA_PMD_REG 2356 (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, &data)); 2357 LOG_VERBOSE(BSL_LS_SOC_PHY, 2358 (BSL_META_U(unit, 2359 "PHY84740 %s module detected: u=%d p=%d\n"), 2360 (data & PHY84740_PMAD_DAC_MODE_MASK) ? 2361 "CR4" : "SR4", unit, port)); 2362 } 2363 } 2364 } else if (!(status & PHY84740_MOD_AUTO_DETECT_STS_I2C_FAIL) && 2365 (MOD_AUTO_DETECT_MSG(pc))) { 2366 uint16 mod_130 = 0, mod_131 = 0; 2367 (void)(READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x81f2, &mod_130)); 2368 (void)(READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x81f3, &mod_131)); 2369 MOD_AUTO_DETECT_MSG(pc) = 0; 2370 LOG_ERROR(BSL_LS_SOC_PHY, 2371 (BSL_META_U(unit, 2372 "PHY84740 i2c failed while detecting module, " 2373 "defaulting to SR(4): u=%d p=%d sts=0x%x (0x%x:0x%x)\n"), 2374 unit, port, status, mod_130, mod_131)); 2375 } 2376 } else { 2377 if (!MOD_AUTO_DETECT_MSG(pc)) { 2378 /* module not present */ 2379 LOG_VERBOSE(BSL_LS_SOC_PHY, 2380 (BSL_META_U(unit, 2381 "PHY84740 module removed u=%d p=%d\n"), 2382 unit, port)); 2383 MOD_AUTO_DETECT_MSG(pc) = 1; 2384 } 2385 } 2386 return SOC_E_NONE; 2387 } 2388 2389 /* 2390 * Function: 2391 * phy_84740_link_get 2392 * Purpose: 2393 * Get layer2 connection status. 2394 * Parameters: 2395 * unit - StrataSwitch unit #. 2396 * port - StrataSwitch port #. 2397 * link - address of memory to store link up/down state. 2398 * Returns: 2399 * SOC_E_NONE 2400 */ 2401 STATIC int phy_84740_link_get(int unit, soc_port_t port, int *link) 2402 { 2403 uint16 pma_mii_stat, pcs_mii_stat, link_stat; 2404 phy_ctrl_t *pc; 2405 phy_ctrl_t *int_pc; 2406 int cur_speed = 0; 2407 int an = 0, an_done = 0; 2408 uint16 speed_val; 2409 uint32 devid; 2410 int rv; 2411 2412 if (link == NULL) { 2413 return SOC_E_NONE; 2414 } 2415 2416 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 2417 *link = FALSE; 2418 return SOC_E_NONE; 2419 } 2420 2421 pc = EXT_PHY_SW_STATE(unit, port); 2422 int_pc = INT_PHY_SW_STATE(unit, port); 2423 2424 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 2425 (pc->unit, pc->port, pc, &devid)); 2426 2427 if (!REVERSE_MODE(pc)) { 2428 if (PCS_REPEATER(pc)) { 2429 rv = PHY_LINK_GET(int_pc->pd, unit, port, link); 2430 return rv; 2431 } 2432 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_REPEATER)) { 2433 rv = PHY_LINK_GET(int_pc->pd, unit, port, link); 2434 } 2435 } 2436 if (FCMAP_PASSTHROUGH(pc)) { 2437 rv = PHY_LINK_GET(int_pc->pd, unit, port, link); 2438 return rv; 2439 } 2440 2441 phy_84740_an_get(unit, port, &an, &an_done); 2442 2443 /* only supports 40G. PHY PCS is not used. Check PMD link only */ 2444 if (PHY84740_SINGLE_PORT_MODE(pc)) { 2445 int serdes_link = TRUE; 2446 2447 if (REVERSE_MODE(pc)) { 2448 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 2449 } 2450 2451 SOC_IF_ERROR_RETURN 2452 (READ_PHY84740_PMA_PMD_STATr(unit, pc, &pma_mii_stat)); 2453 *link = pma_mii_stat == 0xffff ? FALSE : 2454 ((pma_mii_stat & MII_STAT_LA) ? TRUE : FALSE); 2455 2456 if (REVERSE_MODE(pc)) { 2457 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 2458 } 2459 2460 if ((NULL != int_pc) && an) { 2461 PHY_LINK_GET(int_pc->pd, unit, port, &serdes_link); 2462 } 2463 2464 if (MOD_AUTO_DETECT(pc)) { 2465 _phy84740_mod_auto_detect_update(unit, port); 2466 } 2467 2468 *link = (*link) && serdes_link; 2469 return SOC_E_NONE; 2470 } 2471 2472 /* return link false if in the middle of autoneg */ 2473 if (an == TRUE && an_done == FALSE) { 2474 *link = FALSE; 2475 return SOC_E_NONE; 2476 } 2477 2478 /* AN only supports 1G */ 2479 if (!an) { 2480 SOC_IF_ERROR_RETURN 2481 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CTRL2_REG, 2482 &speed_val)); 2483 if ((speed_val & PHY84740_PMAD_CTRL2r_PMA_TYPE_MASK) != 2484 PHY84740_PMAD_CTRL2r_PMA_TYPE_1G_KX) { 2485 cur_speed = 10000; 2486 } 2487 } else { 2488 if (PHY84740_IS_QUADRA(devid)) { 2489 SOC_IF_ERROR_RETURN 2490 (READ_PHY84740_MMF_PMA_PMD_REG 2491 (unit, pc, PHY84740_SPEED_LINK_DETECT_STAT_REG, &speed_val)); 2492 2493 if (speed_val & PHY84740_AN_SPEED_1G_MASK) { 2494 cur_speed = 1000; 2495 } else if (speed_val & PHY84740_AN_SPEED_10G_MASK) { 2496 cur_speed = 10000; 2497 } else { 2498 cur_speed = 1000; 2499 } 2500 } else { 2501 cur_speed = 1000; 2502 } 2503 } 2504 2505 if (REVERSE_MODE(pc)) { 2506 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 2507 } 2508 2509 if (cur_speed == 10000) { /* check all 3 device's link status if 10G */ 2510 2511 /* MMF Link status */ 2512 /* Read Status 2 register to get rid of Local faults */ 2513 SOC_IF_ERROR_RETURN 2514 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_STAT2_REG, 2515 &pma_mii_stat)); 2516 SOC_IF_ERROR_RETURN 2517 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_STAT2_REG, 2518 &pma_mii_stat)); 2519 /* Receive Link status */ 2520 SOC_IF_ERROR_RETURN(READ_PHY84740_PCS_STATr(unit, pc, &pcs_mii_stat)); 2521 2522 SOC_IF_ERROR_RETURN 2523 (READ_PHY84740_PMA_PMD_STATr(unit, pc, &pma_mii_stat)); 2524 2525 /* MMF link status */ 2526 link_stat = pma_mii_stat & pcs_mii_stat; 2527 *link = link_stat == 0xffff ? FALSE : 2528 ((link_stat & MII_STAT_LA) ? TRUE : FALSE); 2529 } else { 2530 SOC_IF_ERROR_RETURN 2531 (READ_PHY84740_MMF_AN_REG(unit, pc, 0xffe1, &link_stat)); 2532 *link = link_stat == 0xffff ? FALSE : 2533 ((link_stat & MII_STAT_LA) ? TRUE : FALSE); 2534 } 2535 2536 if (REVERSE_MODE(pc)) { 2537 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 2538 } 2539 2540 if (MOD_AUTO_DETECT(pc)) { 2541 _phy84740_mod_auto_detect_update(unit, port); 2542 } 2543 LOG_VERBOSE(BSL_LS_SOC_PHY, 2544 (BSL_META_U(unit, 2545 "phy_84740_link_get: u=%d port%d: link:%s\n"), 2546 unit, port, *link ? "Up": "Down")); 2547 2548 return SOC_E_NONE; 2549 } 2550 2551 /* 2552 * Function: 2553 * phy_84740_enable_set 2554 * Purpose: 2555 * Enable/Disable phy 2556 * Parameters: 2557 * unit - StrataSwitch unit #. 2558 * port - StrataSwitch port #. 2559 * enable - on/off state to set 2560 * Returns: 2561 * SOC_E_NONE 2562 */ 2563 2564 STATIC int phy_84740_enable_set(int unit, soc_port_t port, int enable) 2565 { 2566 uint16 data; /* Holder for new value to write to PHY reg */ 2567 uint16 mask; /* Holder for bit mask to update in PHY reg */ 2568 int ix; 2569 uint16 tx_ctrl; 2570 phy_ctrl_t *pc; 2571 2572 pc = EXT_PHY_SW_STATE(unit, port); 2573 if (enable) { 2574 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE); 2575 } else { 2576 PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE); 2577 } 2578 2579 if (REVERSE_MODE(pc) || (pc->flags & PHYCTRL_SYS_SIDE_CTRL)) { 2580 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 2581 } 2582 2583 if (SINGLE_LPMODE(pc) && !(PHY84740_SINGLE_PORT_MODE(pc))) { 2584 /* Use 1.cd16 to disable tx */ 2585 data = enable ? 0 : (1 << 3); 2586 mask = 1 << 3; 2587 SOC_IF_ERROR_RETURN 2588 (MODIFY_PHY84740_MMF_PMA_PMD_REG 2589 (unit, pc, PHY84740_GENSIG_8071_REGISTER, data, mask)); 2590 } else { 2591 /* TX transmitter enable/disable. BCST register in single-port mode */ 2592 data = enable ? 0 : (1 << 0); 2593 mask = 1 << 0; /* Global PMD transmit disable */ 2594 SOC_IF_ERROR_RETURN 2595 (MODIFY_PHY84740_PMA_PMD_TX_DISABLEr(unit, pc, data, mask)); 2596 } 2597 2598 if (REVERSE_MODE(pc)) { 2599 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 2600 } 2601 2602 for (ix = 0; ix < NUM_LANES; ix++) { 2603 if (PHY84740_SINGLE_PORT_MODE(pc)) { 2604 SOC_IF_ERROR_RETURN 2605 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 2606 PHY84740_PMAD_AER_ADDR_REG, 2607 ix)); 2608 } 2609 2610 /* TxOn control */ 2611 SOC_IF_ERROR_RETURN 2612 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 2613 PHY84740_PMAD_OPTICAL_CFG_REG, 2614 enable ? 0 : (1 << 12), 2615 (1 << 12))); 2616 if (enable) { 2617 SOC_IF_ERROR_RETURN 2618 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 2619 PHY84740_PMAD_OPTICAL_CFG_REG, 2620 &data)); 2621 2622 /* c8e4[4] indicates the TX active state when c8e4[12]=0. 0 means TX 2623 * active, 1 means low power mode. This state = TxOnOff pin XOR c800[7] 2624 * Toggle 0xc800[7] to enable the Tx when c8e4[4]=1. 2625 * The default value of c800[7] is 1, if user straps the TxOnOff to 0, 2626 * Then the Tx won't be enabled until this function is called. 2627 */ 2628 2629 SOC_IF_ERROR_RETURN 2630 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 2631 PHY84740_PMAD_OPTICAL_SIG_LVL_REG, 2632 &tx_ctrl)); 2633 tx_ctrl &= (1 << 7); 2634 if (data & (1 << 4)) { 2635 SOC_IF_ERROR_RETURN 2636 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 2637 PHY84740_PMAD_OPTICAL_SIG_LVL_REG, 2638 tx_ctrl ? 0 : (1 << 7), 2639 (1 << 7))); 2640 } 2641 } 2642 /* power on/off the lane */ 2643 SOC_IF_ERROR_RETURN 2644 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 2645 PHY84740_PMAD_OPTICAL_CFG_REG, 2646 enable ? 0 : (1 << 4), (1 << 4))); 2647 if (!PHY84740_SINGLE_PORT_MODE(pc)) { 2648 break; 2649 } 2650 } 2651 if (PHY84740_SINGLE_PORT_MODE(pc)) { 2652 /* point back to lane0 */ 2653 SOC_IF_ERROR_RETURN 2654 (WRITE_PHY84740_MMF_PMA_PMD_REG 2655 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 2656 } 2657 return (SOC_E_NONE); 2658 } 2659 2660 /* 2661 * Function: 2662 * phy_84740_lb_set 2663 * Purpose: 2664 * Put 84740 in PHY PMA/PMD loopback 2665 * Parameters: 2666 * unit - StrataSwitch unit #. 2667 * port - StrataSwitch port #. 2668 * enable - binary value for on/off (1/0) 2669 * Returns: 2670 * SOC_E_NONE 2671 */ 2672 2673 STATIC int phy_84740_lb_set(int unit, soc_port_t port, int enable) 2674 { 2675 phy_ctrl_t *pc; 2676 uint16 tmp; 2677 uint16 lane; 2678 uint16 data16 = 0, mask16 = 0; 2679 int intf_tx; 2680 int intf_rx; 2681 2682 pc = EXT_PHY_SW_STATE(unit, port); 2683 2684 intf_tx = (REVERSE_MODE(pc) || (pc->flags & PHYCTRL_SYS_SIDE_CTRL)) ? 2685 PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE; 2686 2687 intf_rx = ( intf_tx == PHY_DIAG_INTF_LINE ) ? 2688 PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE; 2689 2690 /* TX Enable(Disable) Squelch(FORCE) when we Enable(Disable) loopback */ 2691 SOC_IF_ERROR_RETURN 2692 (_phy_84740_squelch_enable(unit, port, 2693 intf_tx, enable ? TRUE : FALSE, enable ? TRUE : FALSE )); 2694 2695 /* RX Disable(Enable) Squelch when we Enable(Disable) loopback */ 2696 SOC_IF_ERROR_RETURN 2697 (_phy_84740_squelch_enable(unit, port, 2698 intf_rx, enable ? FALSE : TRUE, /* force = */ FALSE)); 2699 2700 tmp = enable ? PHY84740_MII_CTRL_PMA_LOOPBACK : 0; 2701 2702 if (REVERSE_MODE(pc)) { 2703 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 2704 } 2705 2706 SOC_IF_ERROR_RETURN 2707 (MODIFY_PHY84740_PMA_PMD_CTRLr(unit, pc, 2708 tmp, PHY84740_MII_CTRL_PMA_LOOPBACK)); 2709 2710 if (PCS_REPEATER(pc)) { 2711 if ((PHY84740_SINGLE_PORT_MODE(pc))) { 2712 for (lane = 0; lane < NUM_LANES; lane++) { 2713 data16 = 0; 2714 2715 /* point to the each lane starting at lane0 */ 2716 SOC_IF_ERROR_RETURN 2717 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 2718 PHY84740_PMAD_AER_ADDR_REG, 2719 lane)); 2720 2721 SOC_IF_ERROR_RETURN 2722 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd0a, 2723 enable ? 1 : 0, 1)); 2724 2725 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 2726 PHY84740_DIG_CTRL_REG, 2727 &data16)); 2728 2729 /* 1.cd08.10 = 1.cd08.10 XOR 1.cd08.9 */ 2730 tmp = (data16 & PHY84740_RX_POLARITY_FLIP_MASK) << 1; 2731 data16 = (data16 & PHY84740_TX_POLARITY_FLIP_MASK) ^ tmp; 2732 mask16 = PHY84740_TX_POLARITY_FLIP_MASK; 2733 2734 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 2735 PHY84740_DIG_CTRL_REG, 2736 data16, 2737 mask16)); 2738 } 2739 /* point back to lane0 */ 2740 SOC_IF_ERROR_RETURN 2741 (WRITE_PHY84740_MMF_PMA_PMD_REG 2742 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 2743 } else { /* quad-port mode */ 2744 data16 = 0; 2745 SOC_IF_ERROR_RETURN 2746 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd0a, 2747 enable ? 1 : 0, 1)); 2748 2749 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 2750 PHY84740_DIG_CTRL_REG, 2751 &data16)); 2752 2753 /* 1.cd08.10 = 1.cd08.10 XOR 1.cd08.9 */ 2754 tmp = (data16 & PHY84740_RX_POLARITY_FLIP_MASK) << 1; 2755 data16 = (data16 & PHY84740_TX_POLARITY_FLIP_MASK) ^ tmp; 2756 mask16 = PHY84740_TX_POLARITY_FLIP_MASK; 2757 2758 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 2759 (unit, pc, PHY84740_DIG_CTRL_REG, data16, 2760 mask16)); 2761 } 2762 } 2763 2764 if (REVERSE_MODE(pc)) { 2765 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 2766 } 2767 2768 return SOC_E_NONE; 2769 } 2770 2771 /* 2772 * Function: 2773 * phy_84740_lb_get 2774 * Purpose: 2775 * Get 84740 PHY loopback state 2776 * Parameters: 2777 * unit - StrataSwitch unit #. 2778 * port - StrataSwitch port #. 2779 * enable - address of location to store binary value for on/off (1/0) 2780 * Returns: 2781 * SOC_E_NONE 2782 */ 2783 2784 STATIC int phy_84740_lb_get(int unit, soc_port_t port, int *enable) 2785 { 2786 uint16 tmp; 2787 phy_ctrl_t *pc; 2788 2789 pc = EXT_PHY_SW_STATE(unit, port); 2790 2791 if (REVERSE_MODE(pc)) { 2792 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 2793 } 2794 2795 SOC_IF_ERROR_RETURN(READ_PHY84740_PMA_PMD_CTRLr(unit, pc, &tmp)); 2796 /* ctrl != 0xffff check is to handle removable PHY daughter cards */ 2797 *enable = ((tmp != 0xffff) && 2798 (tmp & PHY84740_MII_CTRL_PMA_LOOPBACK)) ? TRUE : FALSE; 2799 2800 if (REVERSE_MODE(pc)) { 2801 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 2802 } 2803 2804 LOG_INFO(BSL_LS_SOC_PHY, 2805 (BSL_META_U(unit, 2806 "phy_84740_lb_get: u=%d port%d: loopback:%s\n"), 2807 unit, port, *enable ? "Enabled": "Disabled")); 2808 2809 return SOC_E_NONE; 2810 } 2811 2812 STATIC int 2813 _phy_84740_control_tx_driver_set(int unit, soc_port_t port, int interface, 2814 soc_phy_control_t type, uint32 value) 2815 { 2816 uint16 data; /* Temporary holder of reg value to be written */ 2817 uint16 mask; /* Bit mask of reg value to be updated */ 2818 int ix; 2819 int lane; 2820 int start; 2821 int end; 2822 uint16 post_pre_tap = 0, force_preemph = 0; 2823 uint16 main_tap = 0; 2824 phy_ctrl_t *pc; /* PHY software state */ 2825 int reg; 2826 uint16 post_tap2 = 0; 2827 uint32 devid = 0; 2828 2829 pc = EXT_PHY_SW_STATE(unit, port); 2830 2831 switch (type) { 2832 case SOC_PHY_CONTROL_DRIVER_CURRENT: 2833 /* fall through */ 2834 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0: 2835 /* fall through */ 2836 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1: 2837 /* fall through */ 2838 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2: 2839 /* fall through */ 2840 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3: 2841 data = (uint16) (value & 0xf); 2842 data = data << 12; 2843 mask = 0xf000; 2844 reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90a : 0xca01; 2845 if ((soc_phy_control_t)type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0) { 2846 lane = 0; 2847 } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1) { 2848 lane = 1; 2849 } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2) { 2850 lane = 2; 2851 } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3) { 2852 lane = 3; 2853 } else { /* SOC_PHY_CONTROL_DRIVER_CURRENT */ 2854 lane = 4; /* all lanes */ 2855 } 2856 if (PHY84740_SINGLE_PORT_MODE(pc)) { 2857 start = lane == 4 ? 0 : lane; 2858 end = lane == 4 ? 4 : lane + 1; 2859 for (ix = start; ix < end; ix++) { 2860 2861 PHY84740_MMF_IF_INTF(unit, pc, interface, 2862 PHY_DIAG_INTF_SYS); 2863 2864 SOC_IF_ERROR_RETURN 2865 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 2866 PHY84740_PMAD_AER_ADDR_REG, 2867 P2L_MAP(pc, ix))); 2868 2869 PHY84740_XFI_IF_INTF(unit, pc, interface, 2870 PHY_DIAG_INTF_SYS); 2871 2872 SOC_IF_ERROR_RETURN 2873 (MODIFY_PHY84740_MMF_PMA_PMD_REG 2874 (unit, pc, reg, data, mask)); 2875 } 2876 } else { 2877 SOC_IF_ERROR_RETURN 2878 (MODIFY_PHY84740_MMF_PMA_PMD_REG 2879 (unit, pc, reg, data, mask)); 2880 } 2881 break; 2882 2883 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 2884 /* fall through */ 2885 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0: 2886 /* fall through */ 2887 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1: 2888 /* fall through */ 2889 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2: 2890 /* fall through */ 2891 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3: 2892 data = (uint16) (value & 0xf); 2893 data = data << 8; 2894 mask = 0x0f00; 2895 reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90a : 0xca01; 2896 if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0) { 2897 lane = 0; 2898 } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1) { 2899 lane = 1; 2900 } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2) { 2901 lane = 2; 2902 } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3) { 2903 lane = 3; 2904 } else { /* SOC_PHY_CONTROL_PRE_DRIVER_CURRENT */ 2905 lane = 4; /* all lanes */ 2906 } 2907 if (PHY84740_SINGLE_PORT_MODE(pc)) { 2908 start = lane == 4 ? 0 : lane; 2909 end = lane == 4 ? 4 : lane + 1; 2910 for (ix = start; ix < end; ix++) { 2911 2912 PHY84740_MMF_IF_INTF(unit, pc, interface, 2913 PHY_DIAG_INTF_SYS); 2914 SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG 2915 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 2916 P2L_MAP(pc, ix))); 2917 2918 PHY84740_XFI_IF_INTF(unit, pc, interface, 2919 PHY_DIAG_INTF_SYS); 2920 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 2921 (unit, pc, reg, data, mask)); 2922 } 2923 } else { 2924 SOC_IF_ERROR_RETURN 2925 (MODIFY_PHY84740_MMF_PMA_PMD_REG 2926 (unit, pc, reg, data, mask)); 2927 } 2928 break; 2929 case SOC_PHY_CONTROL_PREEMPHASIS: 2930 /* fall through */ 2931 case SOC_PHY_CONTROL_PREEMPHASIS_LANE0: 2932 /* fall through */ 2933 case SOC_PHY_CONTROL_PREEMPHASIS_LANE1: 2934 /* fall through */ 2935 case SOC_PHY_CONTROL_PREEMPHASIS_LANE2: 2936 /* fall through */ 2937 case SOC_PHY_CONTROL_PREEMPHASIS_LANE3: 2938 /* The value format: 2939 * bit 16:18: post_tap2 value 2940 * bit 15: 1 enable forced preemphasis ctrl, 0 auto config 2941 * bit 14:10: post_tap value 2942 * bit 09:04: main tap value 2943 * bit 03:00: pre_tap value 2944 * 2945 * set 1.CA07[8] = 0, 1.CA02[15:11] for main_tap and 1.CA05[7:4] for post tap. 2946 * main tap control is in the register field 0xCA02[15:11]. 2947 * If a wrong value is written to the same register, field 0xCA02[9:7], 2948 * it may DAMAGE the device. User must avoid writing to 0xCA02[9:7] 2949 */ 2950 /* Register bit8, 0 force preemphasis, 1 auto config, 1.CA07 */ 2951 force_preemph = PHY84740_PREEMPH_GET_FORCE(value) ? 0 : 2952 PHY84740_PREEMPH_REG_FORCE_MASK; 2953 2954 /* add post tap value */ 2955 post_pre_tap = PHY84740_PREEMPH_GET_POST_TAP(value) << 2956 PHY84740_PREEMPH_REG_POST_TAP_SHFT; 2957 2958 /* add pre tap value */ 2959 post_pre_tap |= PHY84740_PREEMPH_GET_PRE_TAP(value) << 2960 PHY84740_PREEMPH_REG_PRE_TAP_SHFT; 2961 2962 /* main tap in 1.CA02 */ 2963 main_tap = PHY84740_PREEMPH_GET_MAIN_TAP(value) << 2964 PHY84740_PREEMPH_REG_MAIN_TAP_SHFT; 2965 2966 post_tap2 = PHY84740_PREEMP_GET_POST_TAP2(value) << 2967 PHY84740_PREEMPH_REG_POST_TAP2_SHFT; 2968 2969 reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90c : 0xca06; 2970 2971 if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PREEMPHASIS_LANE0) { 2972 lane = 0; 2973 } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PREEMPHASIS_LANE1) { 2974 lane = 1; 2975 } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PREEMPHASIS_LANE2) { 2976 lane = 2; 2977 } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PREEMPHASIS_LANE3) { 2978 lane = 3; 2979 } else { /* SOC_PHY_CONTROL_PREEMPHASIS_LANE */ 2980 lane = 4; /* all lanes */ 2981 } 2982 if (PHY84740_SINGLE_PORT_MODE(pc)) { 2983 start = lane == 4 ? 0 : lane; 2984 end = lane == 4 ? 4 : lane + 1; 2985 } else { 2986 /* just make sure execute once */ 2987 start = 0; 2988 end = 1; 2989 } 2990 for (ix = start; ix < end; ix++) { 2991 if (PHY84740_SINGLE_PORT_MODE(pc)) { 2992 2993 PHY84740_MMF_IF_INTF(unit, pc, interface, 2994 PHY_DIAG_INTF_SYS); 2995 SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG 2996 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 2997 P2L_MAP(pc, ix))); 2998 PHY84740_XFI_IF_INTF(unit, pc, interface, 2999 PHY_DIAG_INTF_SYS); 3000 } 3001 SOC_IF_ERROR_RETURN 3002 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, reg, 3003 post_pre_tap, 3004 PHY84740_PREEMPH_REG_POST_TAP_MASK 3005 | 3006 PHY84740_PREEMPH_REG_PRE_TAP_MASK)); 3007 3008 /* N/A on system side */ 3009 if (interface != PHY_DIAG_INTF_SYS) { 3010 SOC_IF_ERROR_RETURN 3011 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xca07, 3012 force_preemph, 3013 PHY84740_PREEMPH_REG_FORCE_MASK)); 3014 } 3015 3016 /* always clear tx_pwrdn bit. The read/modify/write may accidently 3017 * set the bit 0xCA02[10]. Because the CA02[10] read value is: 3018 * CA02[10]_read_value = CA02[10] OR Digital_State_Machine 3019 * The problem will occur when the Digital_State_Machine output is 1 3020 * at the time of reading this register. 3021 */ 3022 SOC_IF_ERROR_RETURN 3023 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3024 (interface == 3025 PHY_DIAG_INTF_SYS) ? 3026 0xc90b : 0xca02, main_tap, 3027 PHY84740_PREEMPH_REG_MAIN_TAP_MASK 3028 | 3029 PHY84740_PREEMPH_REG_TX_PWRDN_MASK)); 3030 3031 SOC_IF_ERROR_RETURN 3032 (_phy_84740_config_devid(pc->unit, pc->port, pc, &devid)); 3033 3034 /* Only Quadra devices have post tap 2 */ 3035 /* Initialize to zero if i) 40G ii) Backplane package iii) system side */ 3036 if (PHY84740_IS_QUADRA(devid)) { 3037 if (PHY84740_SINGLE_PORT_MODE(pc) || 3038 (interface == PHY_DIAG_INTF_SYS) || 3039 (PHY84740_IS_QUADRA_BACKPLANE(devid))) { 3040 SOC_IF_ERROR_RETURN 3041 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3042 0xca08, 3043 0x0, 3044 PHY84740_PREEMPH_REG_POST_TAP2_MASK)); 3045 } else { 3046 SOC_IF_ERROR_RETURN 3047 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3048 0xca08, 3049 post_tap2, 3050 PHY84740_PREEMPH_REG_POST_TAP2_MASK)); 3051 } 3052 } 3053 } 3054 break; 3055 3056 default: 3057 /* should never get here */ 3058 return SOC_E_PARAM; 3059 } 3060 3061 #ifdef PHY84740_FCS_ERROR_WAR 3062 /* Toggle Transmit lane output so that the link partner 3063 resets itself to a good signal. Othwerise, it could 3064 sync to a sub optimal signal and can see FCS errors. 3065 */ 3066 if (PHY84740_SINGLE_PORT_MODE(pc)) { 3067 start = lane == 4 ? 0 : lane; 3068 end = lane == 4 ? 4 : lane + 1; 3069 } else { 3070 /* just make sure execute once */ 3071 start = 0; 3072 end = 1; 3073 } 3074 for (ix = start; ix < end; ix++) { 3075 if (PHY84740_SINGLE_PORT_MODE(pc)) { 3076 3077 PHY84740_MMF_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS); 3078 SOC_IF_ERROR_RETURN 3079 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3080 PHY84740_PMAD_AER_ADDR_REG, 3081 P2L_MAP(pc, ix))); 3082 PHY84740_XFI_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS); 3083 3084 data = mask = 0x1 << (12 + P2L_MAP(pc, ix)); /* per lane */ 3085 SOC_IF_ERROR_RETURN 3086 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x800e, data, mask)); 3087 3088 data = 0; 3089 SOC_IF_ERROR_RETURN 3090 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x800e, data, mask)); 3091 } else { 3092 data = mask = (lane == 4) ? 0x1 << 11 : /* Global */ 3093 0x1 << (12 + P2L_MAP(pc, lane)); /* per lane */ 3094 SOC_IF_ERROR_RETURN 3095 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x800e, data, mask)); 3096 data = 0; 3097 SOC_IF_ERROR_RETURN 3098 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x800e, data, mask)); 3099 } 3100 } 3101 #endif /* PHY84740_FCS_ERROR_WAR */ 3102 3103 if (PHY84740_SINGLE_PORT_MODE(pc)) { 3104 PHY84740_MMF_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS); 3105 /* point back to lane0 */ 3106 SOC_IF_ERROR_RETURN 3107 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3108 PHY84740_PMAD_AER_ADDR_REG, 0)); 3109 PHY84740_XFI_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS); 3110 } 3111 return SOC_E_NONE; 3112 } 3113 3114 STATIC int 3115 _phy_84740_control_tx_driver_get(int unit, soc_port_t port, int interface, 3116 soc_phy_control_t type, uint32 *value) 3117 { 3118 uint16 data16; /* Temporary holder of a reg value */ 3119 uint16 main_tap; 3120 uint16 post_tap; 3121 int lane; 3122 phy_ctrl_t *pc; /* PHY software state */ 3123 uint16 post_tap2 = 0; 3124 uint16 pre_tap = 0; 3125 uint16 force_preemph = 0; 3126 uint32 devid = 0; 3127 int reg; 3128 3129 pc = EXT_PHY_SW_STATE(unit, port); 3130 3131 data16 = 0; 3132 switch (type) { 3133 case SOC_PHY_CONTROL_PREEMPHASIS: 3134 /* fall through */ 3135 case SOC_PHY_CONTROL_PREEMPHASIS_LANE0: 3136 /* fall through */ 3137 case SOC_PHY_CONTROL_PREEMPHASIS_LANE1: 3138 /* fall through */ 3139 case SOC_PHY_CONTROL_PREEMPHASIS_LANE2: 3140 /* fall through */ 3141 case SOC_PHY_CONTROL_PREEMPHASIS_LANE3: 3142 if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PREEMPHASIS_LANE0) { 3143 lane = 0; 3144 } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PREEMPHASIS_LANE1) { 3145 lane = 1; 3146 } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PREEMPHASIS_LANE2) { 3147 lane = 2; 3148 } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PREEMPHASIS_LANE3) { 3149 lane = 3; 3150 } else { 3151 lane = 0; 3152 } 3153 /* 1.CA05[15] = 0, set 1.CA02[15:11] for main_tap and 3154 * 1.CA05[7:4] for postcursor 3155 */ 3156 if (PHY84740_SINGLE_PORT_MODE(pc)) { 3157 SOC_IF_ERROR_RETURN 3158 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3159 PHY84740_PMAD_AER_ADDR_REG, 3160 P2L_MAP(pc, lane))); 3161 } 3162 SOC_IF_ERROR_RETURN 3163 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3164 (interface == 3165 PHY_DIAG_INTF_SYS) ? 0xc90b : 3166 0xca02, &main_tap)); 3167 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 3168 (unit, pc, 3169 (interface == 3170 PHY_DIAG_INTF_SYS) ? 0xc90c : 0xca06, 3171 &post_tap)); 3172 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 3173 (unit, pc, 3174 (interface == 3175 PHY_DIAG_INTF_SYS) ? 0xc90c : 0xca06, 3176 &pre_tap)); 3177 3178 if (interface != PHY_DIAG_INTF_SYS) { 3179 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 3180 (unit, pc, 3181 0xca07, 3182 &force_preemph)); 3183 /* bit15 force flag, 14:10 post_tap, 09:04 main tap */ 3184 *value = (force_preemph & PHY84740_PREEMPH_REG_FORCE_MASK) ? 0 : 3185 (1 << PHY84740_PREEMPH_CTRL_FORCE_SHFT); 3186 } else { 3187 *value = 0; 3188 } 3189 *value |= ((post_tap & PHY84740_PREEMPH_REG_POST_TAP_MASK) >> 3190 PHY84740_PREEMPH_REG_POST_TAP_SHFT) << 3191 PHY84740_PREEMPH_CTRL_POST_TAP_SHFT; 3192 *value |= ((main_tap & PHY84740_PREEMPH_REG_MAIN_TAP_MASK) >> 3193 PHY84740_PREEMPH_REG_MAIN_TAP_SHFT) << 3194 PHY84740_PREEMPH_CTRL_MAIN_TAP_SHFT; 3195 *value |= ((pre_tap & PHY84740_PREEMPH_REG_PRE_TAP_MASK) >> 3196 PHY84740_PREEMPH_REG_PRE_TAP_SHFT) << 3197 PHY84740_PREEMPH_CTRL_PRE_TAP_SHFT; 3198 SOC_IF_ERROR_RETURN 3199 (_phy_84740_config_devid(pc->unit, pc->port, pc, &devid)); 3200 3201 /* Only Quadra devices have post tap 2 */ 3202 /* Initialize to zero if i) 40G ii) Backplane package iii) system side */ 3203 if (PHY84740_IS_QUADRA(devid)) { 3204 if (PHY84740_SINGLE_PORT_MODE(pc) || 3205 (interface == PHY_DIAG_INTF_SYS) || 3206 (PHY84740_IS_QUADRA_BACKPLANE(devid))) { 3207 post_tap2 = 0; 3208 } else { 3209 SOC_IF_ERROR_RETURN 3210 (READ_PHY84740_MMF_PMA_PMD_REG 3211 (unit, pc, 0xca08, &post_tap2)); 3212 } 3213 *value |= ((post_tap2 & PHY84740_PREEMPH_REG_POST_TAP2_MASK) >> 3214 PHY84740_PREEMPH_REG_POST_TAP2_SHFT) << 3215 PHY84740_PREEMPH_CTRL_POST_TAP2_SHFT; 3216 } 3217 break; 3218 case SOC_PHY_CONTROL_DRIVER_CURRENT: 3219 /* fall through */ 3220 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0: 3221 /* fall through */ 3222 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1: 3223 /* fall through */ 3224 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2: 3225 /* fall through */ 3226 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3: 3227 reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90a : 0xca01; 3228 if ((soc_phy_control_t)type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0) { 3229 lane = 0; 3230 } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1) { 3231 lane = 1; 3232 } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2) { 3233 lane = 2; 3234 } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3) { 3235 lane = 3; 3236 } else { 3237 lane = 0; 3238 } 3239 if (PHY84740_SINGLE_PORT_MODE(pc)) { 3240 SOC_IF_ERROR_RETURN 3241 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3242 PHY84740_PMAD_AER_ADDR_REG, 3243 P2L_MAP(pc, lane))); 3244 } 3245 SOC_IF_ERROR_RETURN 3246 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, reg, &data16)); 3247 *value = (data16 & 0xf000) >> 12; 3248 break; 3249 3250 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 3251 /* fall through */ 3252 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0: 3253 /* fall through */ 3254 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1: 3255 /* fall through */ 3256 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2: 3257 /* fall through */ 3258 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3: 3259 reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90a : 0xca01; 3260 if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0) { 3261 lane = 0; 3262 } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1) { 3263 lane = 1; 3264 } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2) { 3265 lane = 2; 3266 } else if ((soc_phy_control_t)type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3) { 3267 lane = 3; 3268 } else { 3269 lane = 0; 3270 } 3271 if (PHY84740_SINGLE_PORT_MODE(pc)) { 3272 SOC_IF_ERROR_RETURN 3273 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3274 PHY84740_PMAD_AER_ADDR_REG, 3275 P2L_MAP(pc, lane))); 3276 } 3277 SOC_IF_ERROR_RETURN 3278 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, reg, &data16)); 3279 *value = (data16 & 0x0f00) >> 8; 3280 break; 3281 3282 default: 3283 /* should never get here */ 3284 return SOC_E_PARAM; 3285 } 3286 3287 if (PHY84740_SINGLE_PORT_MODE(pc)) { 3288 /* point back to lane0 */ 3289 SOC_IF_ERROR_RETURN 3290 (WRITE_PHY84740_MMF_PMA_PMD_REG 3291 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 3292 } 3293 return SOC_E_NONE; 3294 } 3295 3296 STATIC int 3297 _phy_84740_control_edc_mode_set(int unit, soc_port_t port, uint32 value) 3298 { 3299 uint16 data16; 3300 uint16 mask16; 3301 phy_ctrl_t *pc; /* PHY software state */ 3302 int ix; 3303 3304 pc = EXT_PHY_SW_STATE(unit, port); 3305 3306 /* clear software overrides */ 3307 mask16 = 0; 3308 if (!RX_LOS(pc)) { 3309 mask16 |= PHY84740_RXLOS_OVERRIDE_MASK; 3310 } 3311 /* default: override MOD_ABS signalling */ 3312 if (!MOD_ABS(pc)) { 3313 mask16 |= PHY84740_MOD_ABS_OVERRIDE_MASK; 3314 } 3315 3316 if (PHY84740_SINGLE_PORT_MODE(pc)) { 3317 for (ix = 0; ix < NUM_LANES; ix++) { 3318 SOC_IF_ERROR_RETURN 3319 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3320 PHY84740_PMAD_AER_ADDR_REG, 3321 ix)); 3322 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 3323 (unit, pc, PHY84740_PMAD_OPTICAL_CFG_REG, 0, 3324 mask16)); 3325 } 3326 } else { 3327 SOC_IF_ERROR_RETURN 3328 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3329 PHY84740_PMAD_OPTICAL_CFG_REG, 0, 3330 mask16)); 3331 } 3332 3333 for (ix = 0; ix < NUM_LANES; ix++) { 3334 if (PHY84740_SINGLE_PORT_MODE(pc)) { 3335 SOC_IF_ERROR_RETURN 3336 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3337 PHY84740_PMAD_AER_ADDR_REG, 3338 ix)); 3339 } 3340 3341 /* EDC mode programming sequence */ 3342 mask16 = 1 << 9; 3343 3344 /* induce LOS condition: toggle register bit 0xc800.9 */ 3345 SOC_IF_ERROR_RETURN 3346 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3347 PHY84740_PMAD_OPTICAL_SIG_LVL_REG, 3348 &data16)); 3349 3350 /* only change toggled bit 9 */ 3351 SOC_IF_ERROR_RETURN 3352 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3353 PHY84740_PMAD_OPTICAL_SIG_LVL_REG, 3354 ~data16, mask16)); 3355 3356 /* program EDC mode */ 3357 SOC_IF_ERROR_RETURN 3358 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1A, (uint16) value, 3359 PHY84740_EDC_MODE_MASK)); 3360 3361 /* remove LOS condition: restore back original value of bit 0xc800.9 */ 3362 SOC_IF_ERROR_RETURN 3363 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3364 PHY84740_PMAD_OPTICAL_SIG_LVL_REG, 3365 data16, mask16)); 3366 3367 if (!PHY84740_SINGLE_PORT_MODE(pc)) { 3368 break; 3369 } 3370 } 3371 3372 /* restore software override */ 3373 data16 = 0; 3374 mask16 = PHY84740_RXLOS_OVERRIDE_MASK | PHY84740_MOD_ABS_OVERRIDE_MASK; 3375 if (!RX_LOS(pc)) { 3376 data16 |= PHY84740_RXLOS_OVERRIDE_MASK; 3377 } 3378 /* default: override MOD_ABS signalling */ 3379 if (!MOD_ABS(pc)) { 3380 data16 |= PHY84740_MOD_ABS_OVERRIDE_MASK; 3381 } 3382 3383 if (PHY84740_SINGLE_PORT_MODE(pc)) { 3384 for (ix = 0; ix < NUM_LANES; ix++) { 3385 SOC_IF_ERROR_RETURN 3386 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3387 PHY84740_PMAD_AER_ADDR_REG, 3388 ix)); 3389 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 3390 (unit, pc, PHY84740_PMAD_OPTICAL_CFG_REG, 3391 data16, mask16)); 3392 } 3393 3394 /* point back to lane0 */ 3395 SOC_IF_ERROR_RETURN 3396 (WRITE_PHY84740_MMF_PMA_PMD_REG 3397 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 3398 } else { 3399 /* XXX temp 0xc0c0: RXLOS override: 0x0808 MOD_ABS override */ 3400 SOC_IF_ERROR_RETURN 3401 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3402 PHY84740_PMAD_OPTICAL_CFG_REG, 3403 data16, mask16)); 3404 } 3405 3406 return SOC_E_NONE; 3407 } 3408 3409 /* 3410 * enable/disable syncE recoverd clock for 10G/40G modes. 3411 */ 3412 STATIC int 3413 _phy_84740_control_recovery_clock_set(int unit, soc_port_t port, int enable) 3414 { 3415 uint16 data16; 3416 uint16 mask16; 3417 int lane; 3418 phy_ctrl_t *pc; /* PHY software state */ 3419 3420 pc = EXT_PHY_SW_STATE(unit, port); 3421 3422 /* 3423 * 1.CB27[3] = 0 to disable FC recovered clock to appear at TESTP/N. 3424 * 1.CA1D[11] = 0 to disable PLL clock to appear at TESTP/N. 3425 * 1.CA1D[1:0] = 00 to disable bandgap voltage and vco_control voltage appear at TESTP/N. 3426 * 1.CB27[0] = 1 enables rx recovered clock to come out of TESTP/N pads. 3427 * 1.CB26[14:13] = 11 for 156.25Mhz syncE divider select 3428 * 1.CB26[12] = 1 for syncE clock out. 3429 */ 3430 3431 for (lane = 0; lane < NUM_LANES; lane++) { 3432 if (PHY84740_SINGLE_PORT_MODE(pc)) { 3433 SOC_IF_ERROR_RETURN 3434 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3435 PHY84740_PMAD_AER_ADDR_REG, 3436 lane)); 3437 } 3438 /* set to 0 in both enable/disable cases */ 3439 3440 /* disable FC recovered clock to appear at TESTP/N. */ 3441 SOC_IF_ERROR_RETURN 3442 (MODIFY_PHY84740_MMF_PMA_PMD_REG 3443 (unit, pc, PHY84740_PMAD_RECOVERY_CLK_REG, 0, (1 << 3))); 3444 /* disable PLL clock to appear at TESTP/N 3445 * disable bandgap voltage and vco_control voltage appear at TESTP/N 3446 */ 3447 mask16 = (1 << 11) | 0x3; 3448 SOC_IF_ERROR_RETURN 3449 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1D, 0, mask16)); 3450 3451 /* enables rx recovered clock to come out of TESTP/N pads */ 3452 mask16 = PHY84740_RECOVERY_CLK_ENABLE_MASK; 3453 data16 = enable ? mask16 : 0; 3454 SOC_IF_ERROR_RETURN 3455 (MODIFY_PHY84740_MMF_PMA_PMD_REG 3456 (unit, pc, PHY84740_PMAD_RECOVERY_CLK_REG, data16, mask16)); 3457 3458 /* always use bits 14:13 to select the sync clock frequency */ 3459 mask16 = (0x1 << 12); 3460 data16 = mask16; 3461 SOC_IF_ERROR_RETURN 3462 (MODIFY_PHY84740_MMF_PMA_PMD_REG 3463 (unit, pc, PHY84740_PMAD_RECOVERY_CLK_FREQ_REG, data16, mask16)); 3464 if (!PHY84740_SINGLE_PORT_MODE(pc)) { 3465 break; 3466 } 3467 } 3468 if (PHY84740_SINGLE_PORT_MODE(pc)) { 3469 /* point back to lane0 */ 3470 SOC_IF_ERROR_RETURN 3471 (WRITE_PHY84740_MMF_PMA_PMD_REG 3472 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 3473 } 3474 return SOC_E_NONE; 3475 } 3476 3477 /* 3478 * set the frequency of the syncE recoverd clock. 3479 */ 3480 STATIC int 3481 _phy_84740_control_recovery_clock_freq_set(int unit, soc_port_t port, int freq) 3482 { 3483 phy_ctrl_t *pc; /* PHY software state */ 3484 int lane; 3485 uint16 freq_ctrl; 3486 3487 pc = EXT_PHY_SW_STATE(unit, port); 3488 3489 /* 3490 * 1.CB26[14:13] 3491 * Select the frequency of SyncE clock to be sent to the test port: 3492 * 00 : Power down syncE clock dividers 3493 * 01 : 125 MHz (divide by 82.5) 3494 * 10 : 195.3125 MHz (divide by 52.8) 3495 * 11 : 156.25 MHz (divide by 66) 3496 */ 3497 3498 switch (freq) { 3499 case 125000: 3500 freq_ctrl = 0x1; 3501 break; 3502 case 195312: 3503 freq_ctrl = 0x2; 3504 break; 3505 case 156250: 3506 freq_ctrl = 0x3; 3507 break; 3508 default: 3509 freq_ctrl = 0x0; 3510 break; 3511 } 3512 3513 for (lane = 0; lane < NUM_LANES; lane++) { 3514 if (PHY84740_SINGLE_PORT_MODE(pc)) { 3515 SOC_IF_ERROR_RETURN 3516 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3517 PHY84740_PMAD_AER_ADDR_REG, 3518 lane)); 3519 } 3520 3521 SOC_IF_ERROR_RETURN 3522 (MODIFY_PHY84740_MMF_PMA_PMD_REG 3523 (unit, pc, PHY84740_PMAD_RECOVERY_CLK_FREQ_REG, 3524 PHY84740_RECOVERY_CLK_FREQf(freq_ctrl), 3525 PHY84740_RECOVERY_CLK_FREQ_MASK)); 3526 3527 if (!PHY84740_SINGLE_PORT_MODE(pc)) { 3528 break; 3529 } 3530 } 3531 if (PHY84740_SINGLE_PORT_MODE(pc)) { 3532 /* point back to lane0 */ 3533 SOC_IF_ERROR_RETURN 3534 (WRITE_PHY84740_MMF_PMA_PMD_REG 3535 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 3536 } 3537 return SOC_E_NONE; 3538 } 3539 3540 STATIC int 3541 _phy_84740_control_prbs_tx_invert_data_set(int unit, soc_port_t port, 3542 int intf, int invert) 3543 { 3544 phy_ctrl_t *pc; /* PHY software state */ 3545 uint16 data16, speed_val, mask16 = 0x1 << 2; 3546 uint32 devid; 3547 int lane = 0; 3548 pc = EXT_PHY_SW_STATE(unit, port); 3549 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 3550 (pc->unit, pc->port, pc, &devid)); 3551 if (PHY84740_SINGLE_PORT_MODE(pc)) { 3552 if (PHY_DIAG_INTF_SYS == intf) { 3553 data16 = invert ? PHY84740_USER_PRBS_TX_INVERT : 0; 3554 mask16 = PHY84740_USER_PRBS_TX_INVERT; 3555 for (lane = 0; lane < NUM_LANES; lane++) { 3556 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 3557 SOC_IF_ERROR_RETURN 3558 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3559 PHY84740_PMAD_AER_ADDR_REG, lane)); 3560 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 3561 SOC_IF_ERROR_RETURN 3562 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3563 PHY84740_USER_PRBS_CONTROL_0_REGISTER, 3564 data16, mask16)); 3565 } 3566 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 3567 SOC_IF_ERROR_RETURN 3568 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3569 PHY84740_PMAD_AER_ADDR_REG, 0)); 3570 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 3571 } else { 3572 if(PHY84740_IS_QUADRA(devid)) { 3573 /* 3574 * In Quadra PRBS TX is inverted in PACKAGE itself, 3575 * by default bit no. 4 and bit no.3 in reg 0xcd60 is set to 3576 * 1 (in this mode),which means twice inversion of PRBS TX 3577 * (means no inversion in TX) 3578 * only PRBS RX is inverted,so prbs lock won't happen,to avoid 3579 * this situation we are clearing bit no.4 in 0xcd60,means 3580 * both TX and RX inverted leads to zero prbs error. 3581 3582 * NOTE:Bit no.6 in 0xcd60 is not considered in 40G mode. 3583 * The autodetect is forced to disable. 3584 */ 3585 data16 = invert ? 0 : PHY84740_USER_PRBS_TX_INVERT; 3586 mask16 = PHY84740_USER_PRBS_TX_INVERT; 3587 for (lane = 0; lane < NUM_LANES; lane++) { 3588 SOC_IF_ERROR_RETURN 3589 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3590 PHY84740_PMAD_AER_ADDR_REG, lane)); 3591 SOC_IF_ERROR_RETURN 3592 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3593 PHY84740_UDRCD_PRBS20_CONTROL_REGISTER, 3594 data16,mask16)); 3595 } 3596 SOC_IF_ERROR_RETURN 3597 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3598 PHY84740_PMAD_AER_ADDR_REG, 0)); 3599 } else { 3600 return SOC_E_UNAVAIL; 3601 } 3602 } 3603 } else { /* quad-port mode */ 3604 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 3605 (pc->unit, pc->port, pc, &devid)); 3606 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 3607 (unit, pc, 0xc81f, &speed_val)); 3608 if (PHY84740_IS_QUADRA(devid) && (speed_val & (1 << 2))) { 3609 data16 = invert ? mask16 : 0; 3610 SOC_IF_ERROR_RETURN 3611 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x8019, data16, mask16)); 3612 } else { 3613 /* tx inversion */ 3614 data16 = invert ? PHY84740_USER_PRBS_TX_INVERT : 0; 3615 SOC_IF_ERROR_RETURN 3616 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3617 PHY84740_USER_PRBS_CONTROL_0_REGISTER, 3618 data16, 3619 PHY84740_USER_PRBS_TX_INVERT)); 3620 } 3621 } 3622 return SOC_E_NONE; 3623 } 3624 3625 STATIC int 3626 _phy_84740_control_prbs_rx_invert_data_set(int unit, soc_port_t port, 3627 int intf, int invert) 3628 { 3629 phy_ctrl_t *pc; /* PHY software state */ 3630 uint16 data16; 3631 uint16 mask16; 3632 int lane = 0; 3633 pc = EXT_PHY_SW_STATE(unit, port); 3634 3635 if (PHY84740_SINGLE_PORT_MODE(pc)) { 3636 if (PHY_DIAG_INTF_SYS == intf) { 3637 data16 = invert ? PHY84740_USER_PRBS_RX_INVERT : 0; 3638 mask16 = PHY84740_USER_PRBS_RX_INVERT; 3639 3640 for (lane = 0; lane < NUM_LANES; lane++) { 3641 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 3642 SOC_IF_ERROR_RETURN 3643 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3644 PHY84740_PMAD_AER_ADDR_REG, lane)); 3645 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 3646 SOC_IF_ERROR_RETURN 3647 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3648 PHY84740_USER_PRBS_CONTROL_0_REGISTER, 3649 data16, mask16)); 3650 } 3651 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 3652 SOC_IF_ERROR_RETURN 3653 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3654 PHY84740_PMAD_AER_ADDR_REG, 0)); 3655 } else { 3656 return SOC_E_UNAVAIL; 3657 } 3658 } else { /* quad-port mode */ 3659 /* rx inversion */ 3660 data16 = invert ? PHY84740_USER_PRBS_RX_INVERT : 0; 3661 mask16 = PHY84740_USER_PRBS_RX_INVERT; 3662 SOC_IF_ERROR_RETURN 3663 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3664 PHY84740_USER_PRBS_CONTROL_0_REGISTER, 3665 data16, mask16)); 3666 } 3667 return SOC_E_NONE; 3668 } 3669 3670 STATIC int 3671 _phy_84740_control_prbs_polynomial_set(int unit, soc_port_t port, int poly_ctrl, 3672 int intf, int tx) 3673 { /* tx or rx */ 3674 phy_ctrl_t *pc; /* PHY software state */ 3675 uint16 data16; 3676 uint16 mask16, speed_val; 3677 uint32 devid; 3678 int lane=0; 3679 /* 3680 * poly_ctrl: 3681 * 0x0 = prbs7 3682 * 0x1 = prbs15 3683 * 0x2 = prbs23 3684 * 0x3 = prbs31 3685 * 0x4 = prbs9 3686 * 0x5 = prbs11 3687 */ 3688 pc = EXT_PHY_SW_STATE(unit, port); 3689 SOC_IF_ERROR_RETURN( 3690 _phy_84740_config_devid(pc->unit,pc->port, pc, &devid)); 3691 if (PHY84740_SINGLE_PORT_MODE(pc)) { 3692 if (PHY_DIAG_INTF_SYS == intf) { 3693 mask16 = PHY84740_40G_SYS_PRBS_MASK; 3694 if (poly_ctrl == SOC_PHY_PRBS_POLYNOMIAL_X31_X28_1) { 3695 data16 = PHY84740_40G_SYS_PRBS31; 3696 } else if (poly_ctrl == SOC_PHY_PRBS_POLYNOMIAL_X9_X5_1) { 3697 data16 = PHY84740_40G_SYS_PRBS9; 3698 } else if (poly_ctrl == SOC_PHY_PRBS_POLYNOMIAL_X7_X6_1) { 3699 data16 = PHY84740_40G_SYS_PRBS7; 3700 } else if (poly_ctrl == SOC_PHY_PRBS_POLYNOMIAL_X15_X14_1) { 3701 data16 = PHY84740_40G_SYS_PRBS15; 3702 } else if (poly_ctrl == SOC_PHY_PRBS_POLYNOMIAL_X23_X18_1) { 3703 data16 = PHY84740_40G_SYS_PRBS23; 3704 } else if (poly_ctrl == SOC_PHY_PRBS_POLYNOMIAL_X11_X9_1) { 3705 data16 = PHY84740_40G_SYS_PRBS11; 3706 } else { 3707 return SOC_E_PARAM; 3708 } 3709 if (!tx) { 3710 data16 <<= 12; 3711 mask16 <<= 12; 3712 } 3713 for (lane = 0; lane < NUM_LANES; lane++) { 3714 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 3715 SOC_IF_ERROR_RETURN 3716 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3717 PHY84740_PMAD_AER_ADDR_REG, lane)); 3718 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 3719 SOC_IF_ERROR_RETURN 3720 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3721 PHY84740_USER_PRBS_CONTROL_0_REGISTER, 3722 data16,mask16)); 3723 } 3724 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 3725 SOC_IF_ERROR_RETURN 3726 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3727 PHY84740_PMAD_AER_ADDR_REG, 0)); 3728 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 3729 3730 } else { 3731 if(PHY84740_IS_QUADRA(devid)) { 3732 mask16 = PHY84740_40G_PRBS31 | PHY84740_40G_PRBS9 ; 3733 if (poly_ctrl == SOC_PHY_PRBS_POLYNOMIAL_X31_X28_1) { 3734 data16 = PHY84740_40G_PRBS31; 3735 } else if (poly_ctrl == SOC_PHY_PRBS_POLYNOMIAL_X9_X5_1) { 3736 data16 = PHY84740_40G_PRBS9; 3737 } else { 3738 return SOC_E_PARAM; 3739 } 3740 SOC_IF_ERROR_RETURN 3741 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3742 PHY84740_FORTYG_SQ_WAVE_TESTING_CONTROL_REGISTER, 3743 data16,mask16)); 3744 } else { 3745 /* only two types available PRBS9 and PRBS31 */ 3746 if (poly_ctrl == 3) { 3747 data16 = PHY84740_40G_PRBS31; 3748 } else { 3749 data16 = PHY84740_40G_PRBS9; 3750 } 3751 SOC_IF_ERROR_RETURN 3752 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3753 PHY84740_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS, 3754 data16, PHY84740_40G_PRBS9 | PHY84740_40G_PRBS31)); 3755 } 3756 } 3757 } else { /* quad-port mode */ 3758 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 3759 (pc->unit, pc->port, pc, &devid)); 3760 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 3761 (unit, pc, 0xc81f, &speed_val)); 3762 3763 if (PHY84740_IS_QUADRA(devid) && (speed_val & (1 << 2))) { 3764 if (poly_ctrl == 0) { 3765 poly_ctrl = 0; 3766 } else if (poly_ctrl == 3) { 3767 poly_ctrl = 3; 3768 } else if (poly_ctrl == 4) { 3769 poly_ctrl = 1; 3770 } else if (poly_ctrl == 5) { 3771 poly_ctrl = 2; 3772 } else { 3773 return SOC_E_PARAM; 3774 } 3775 SOC_IF_ERROR_RETURN 3776 (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0x8015, 0x0010)); 3777 SOC_IF_ERROR_RETURN 3778 (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0x8000, 0x2c22)); 3779 SOC_IF_ERROR_RETURN 3780 (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0x8017, 0x0)); 3781 SOC_IF_ERROR_RETURN 3782 (MODIFY_PHY84740_MMF_AN_REG 3783 (unit, pc, 0x8019, poly_ctrl, 0x0003)); 3784 } else { 3785 /* 001 : prbs7 3786 010 : prbs9 3787 011 : prbs11 3788 100 : prbs15 3789 101 : prbs23 3790 110 : prbs31 3791 */ 3792 if (poly_ctrl == 0) { 3793 data16 = 1; 3794 } else if (poly_ctrl == 1) { 3795 data16 = 4; 3796 } else if (poly_ctrl == 2) { 3797 data16 = 5; 3798 } else if (poly_ctrl == 3) { 3799 data16 = 6; 3800 } else if (poly_ctrl == 4) { 3801 data16 = 2; 3802 } else if (poly_ctrl == 5) { 3803 data16 = 3; 3804 } else { 3805 return SOC_E_PARAM; 3806 } 3807 mask16 = PHY84740_USER_PRBS_TYPE_MASK; 3808 3809 /* default is tx */ 3810 if (!tx) { /* rx */ 3811 data16 = data16 << 12; 3812 mask16 = mask16 << 12; 3813 } 3814 3815 /* both tx/rx types */ 3816 SOC_IF_ERROR_RETURN 3817 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3818 PHY84740_USER_PRBS_CONTROL_0_REGISTER, 3819 data16, mask16)); 3820 } 3821 } 3822 return SOC_E_NONE; 3823 } 3824 3825 STATIC int 3826 _phy_84740_control_prbs_enable_set(int unit, soc_port_t port, 3827 int intf, int enable) 3828 { 3829 phy_ctrl_t *pc; /* PHY software state */ 3830 int lane; 3831 int repeater_mode; 3832 uint16 data16, speed_val, regval=0,mask16; 3833 uint32 devid; 3834 3835 pc = EXT_PHY_SW_STATE(unit, port); 3836 SOC_IF_ERROR_RETURN( 3837 _phy_84740_config_devid(pc->unit,pc->port, pc, &devid)); 3838 if (PHY84740_SINGLE_PORT_MODE(pc)) { 3839 if (PHY_DIAG_INTF_SYS == intf) { 3840 for (lane = 0; lane < NUM_LANES; lane++) { 3841 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 3842 SOC_IF_ERROR_RETURN 3843 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3844 PHY84740_PMAD_AER_ADDR_REG, lane)); 3845 SOC_IF_ERROR_RETURN 3846 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16)); 3847 if ((data16 & PHY84740_40G_SYS_REP_MODE_ENABLE ) == 3848 PHY84740_40G_SYS_REP_MODE_ENABLE ) { 3849 regval = enable ? PHY84740_40G_SYS_PRBS_ENABLE : 0; 3850 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 3851 SOC_IF_ERROR_RETURN 3852 (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0x810c,regval)); 3853 } 3854 } 3855 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 3856 SOC_IF_ERROR_RETURN 3857 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3858 PHY84740_PMAD_AER_ADDR_REG, 3859 0)); 3860 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 3861 } else { 3862 if(PHY84740_IS_QUADRA(devid)) { 3863 mask16 = PHY84740_40G_PRBS_ENABLE; 3864 data16 = enable ? PHY84740_40G_PRBS_ENABLE : 0; 3865 SOC_IF_ERROR_RETURN 3866 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3867 PHY84740_FORTYG_SQ_WAVE_TESTING_CONTROL_REGISTER, 3868 data16,mask16)); 3869 /* 3870 * In Quadra PRBS TX is inverted in PACKAGE itself, 3871 * by default bit no. 4 and bit no.3 in reg 0xcd60 is set to 3872 * 1 in this mode,which means twice inversion of PRBS TX 3873 * (means no inversion in TX) 3874 * only PRBS RX is inverted,so prbs lock won't happen,to avoid 3875 * this situation we are clearing bit no.4 in 0xcd60,means 3876 * both TX and RX inverted leads to zero prbs error. 3877 3878 * NOTE:Bit no.6 in 0xcd60 is not considered in 40G mode. 3879 * The autodetect is forced to disable. 3880 */ 3881 data16 = enable ? 0 : PHY84740_USER_PRBS_TX_INVERT; 3882 mask16 = PHY84740_USER_PRBS_TX_INVERT; 3883 for (lane = 0; lane < NUM_LANES; lane++) { 3884 SOC_IF_ERROR_RETURN 3885 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3886 PHY84740_PMAD_AER_ADDR_REG, lane)); 3887 SOC_IF_ERROR_RETURN 3888 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3889 PHY84740_UDRCD_PRBS20_CONTROL_REGISTER, 3890 data16,mask16)); 3891 } 3892 } else { 3893 for (lane = 0; lane < NUM_LANES; lane++) { 3894 SOC_IF_ERROR_RETURN 3895 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3896 PHY84740_PMAD_AER_ADDR_REG, 3897 lane)); 3898 3899 /* GENSIG_8071_REGISTER Clocks enable */ 3900 SOC_IF_ERROR_RETURN 3901 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3902 PHY84740_GENSIG_8071_REGISTER, 3903 enable ? 0x3 : 0)); 3904 /* RESET_CONTROL_REGISTER */ 3905 SOC_IF_ERROR_RETURN 3906 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3907 PHY84740_RESET_CONTROL_REGISTER, 3908 0x0)); 3909 3910 /* DATA_MUX_SEL_CNTRL_REGISTER */ 3911 SOC_IF_ERROR_RETURN 3912 (WRITE_PHY84740_MMF_PMA_PMD_REG 3913 (unit, pc, 0xcd58, enable ? 0x2 : 0)); 3914 3915 /* 40G_PRBS_PATTERN_TESTING_CONTROL_STATUS */ 3916 SOC_IF_ERROR_RETURN 3917 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3918 PHY84740_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS, 3919 enable ? 3920 PHY84740_40G_PRBS_ENABLE : 0, 3921 0xf)); 3922 } 3923 } 3924 } 3925 /* point back to lane0 */ 3926 SOC_IF_ERROR_RETURN 3927 (WRITE_PHY84740_MMF_PMA_PMD_REG 3928 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 3929 } else { /* quad-port mode */ 3930 SOC_IF_ERROR_RETURN 3931 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16)); 3932 3933 repeater_mode = ((data16 & 0x6) == 0x6) ? TRUE : FALSE; 3934 if (repeater_mode) { 3935 /* Enable retimer prbs clocks inside SFI */ 3936 SOC_IF_ERROR_RETURN 3937 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3938 PHY84740_GENSIG_8071_REGISTER, 3939 enable ? 0x3 : 0, 0x3)); 3940 3941 /* Enable the retimer datapath */ 3942 SOC_IF_ERROR_RETURN 3943 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd58, 3944 enable ? 0x2 : 0, 0x3)); 3945 } 3946 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 3947 (pc->unit, pc->port, pc, &devid)); 3948 3949 SOC_IF_ERROR_RETURN 3950 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81f, &speed_val)); 3951 if (PHY84740_IS_QUADRA(devid) && (speed_val & (1 << 2))) { 3952 SOC_IF_ERROR_RETURN 3953 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16)); 3954 if (data16 & PHY84740_RX_REPEATER_MASK) { 3955 SOC_IF_ERROR_RETURN 3956 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc806, 3957 enable ? 0 : PHY84740_TX_REPEATER_ENABLE, 3958 PHY84740_TX_REPEATER_MASK)); 3959 } 3960 SOC_IF_ERROR_RETURN 3961 (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0x80b1, 0x0007)); 3962 if (enable) { 3963 SOC_IF_ERROR_RETURN 3964 (MODIFY_PHY84740_MMF_AN_REG 3965 (unit, pc, 0x8019, 0x0008, 0x0008)); 3966 } else { 3967 SOC_IF_ERROR_RETURN 3968 (MODIFY_PHY84740_MMF_AN_REG 3969 (unit, pc, 0x8019, 0x0000, 0x0008)); 3970 } 3971 3972 } else { 3973 /* clear PRBS control if disabled */ 3974 if (!enable) { 3975 SOC_IF_ERROR_RETURN 3976 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3977 PHY84740_USER_PRBS_CONTROL_0_REGISTER, 3978 0, 3979 PHY84740_USER_PRBS_TYPE_MASK | PHY84740_USER_PRBS_TYPE_MASK << 12)); /* rx type */ 3980 } 3981 /* program the PRBS enable */ 3982 SOC_IF_ERROR_RETURN 3983 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 3984 PHY84740_USER_PRBS_CONTROL_0_REGISTER, 3985 enable ? 3986 PHY84740_USER_PRBS_ENABLE : 0, 3987 PHY84740_USER_PRBS_ENABLE)); 3988 } 3989 } 3990 return SOC_E_NONE; 3991 } 3992 3993 STATIC int 3994 _phy_84740_control_prbs_enable_get(int unit, soc_port_t port,int intf, uint32 *value) 3995 { 3996 uint16 data16, speed_val,temp=0; 3997 phy_ctrl_t *pc; /* PHY software state */ 3998 uint32 devid; 3999 int lane = 0; 4000 4001 pc = EXT_PHY_SW_STATE(unit, port); 4002 SOC_IF_ERROR_RETURN( 4003 _phy_84740_config_devid(pc->unit,pc->port, pc, &devid)); 4004 if (PHY84740_SINGLE_PORT_MODE(pc)) { 4005 if (PHY_DIAG_INTF_SYS == intf) { 4006 temp = PHY84740_40G_SYS_PRBS_ENABLE_MASK; 4007 for (lane = 0; lane < NUM_LANES; lane++) { 4008 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 4009 SOC_IF_ERROR_RETURN 4010 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4011 PHY84740_PMAD_AER_ADDR_REG, lane)); 4012 SOC_IF_ERROR_RETURN 4013 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16)); 4014 if ((data16 & PHY84740_40G_SYS_REP_MODE_ENABLE) == 4015 PHY84740_40G_SYS_REP_MODE_ENABLE) { 4016 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 4017 SOC_IF_ERROR_RETURN 4018 (READ_PHY84740_MMF_AN_REG(unit, pc, 0x810c, &data16)); 4019 if ((temp & data16) != PHY84740_40G_SYS_PRBS_ENABLE) { 4020 *value = FALSE; 4021 break; 4022 } 4023 *value = TRUE ; 4024 } 4025 } 4026 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 4027 SOC_IF_ERROR_RETURN 4028 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4029 PHY84740_PMAD_AER_ADDR_REG, 0)); 4030 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 4031 } else { 4032 if(PHY84740_IS_QUADRA(devid)) { 4033 SOC_IF_ERROR_RETURN 4034 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4035 PHY84740_FORTYG_SQ_WAVE_TESTING_CONTROL_REGISTER, 4036 &data16)); 4037 data16 = data16 & PHY84740_40G_PRBS_ENABLE; 4038 *value = (data16 == PHY84740_40G_PRBS_ENABLE) ? TRUE : FALSE; 4039 } else { 4040 SOC_IF_ERROR_RETURN 4041 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4042 PHY84740_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS, 4043 &data16)); 4044 if ((data16 & PHY84740_40G_PRBS_ENABLE) == PHY84740_40G_PRBS_ENABLE) { 4045 *value = TRUE; 4046 } else { 4047 *value = FALSE; 4048 } 4049 } 4050 } 4051 } else { /* quad-port mode */ 4052 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 4053 (pc->unit, pc->port, pc, &devid)); 4054 4055 SOC_IF_ERROR_RETURN 4056 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81f, &speed_val)); 4057 4058 if (PHY84740_IS_QUADRA(devid) && (speed_val & (1 << 2))) { 4059 SOC_IF_ERROR_RETURN 4060 (READ_PHY84740_MMF_AN_REG(unit, pc, 0x8019, &data16)); 4061 *value = (data16 & 0x0008) ? TRUE : FALSE; 4062 } else { 4063 SOC_IF_ERROR_RETURN 4064 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4065 PHY84740_USER_PRBS_CONTROL_0_REGISTER, 4066 &data16)); 4067 if (data16 & PHY84740_USER_PRBS_ENABLE) { 4068 *value = TRUE; 4069 } else { 4070 *value = FALSE; 4071 } 4072 } 4073 } 4074 return SOC_E_NONE; 4075 } 4076 4077 STATIC int 4078 _phy_84740_control_prbs_polynomial_get(int unit, soc_port_t port, 4079 int intf, uint32 *value) 4080 { 4081 phy_ctrl_t *pc; /* PHY software state */ 4082 uint16 poly_ctrl, speed_val, data16=0; 4083 uint32 devid; 4084 int lane = 0; 4085 4086 pc = EXT_PHY_SW_STATE(unit, port); 4087 /* 4088 * poly_ctrl: 4089 * 0x0 = prbs7 4090 * 0x1 = prbs15 4091 * 0x2 = prbs23 4092 * 0x3 = prbs31 4093 * 0x4 = prbs9 4094 * 0x5 = prbs11 4095 */ 4096 SOC_IF_ERROR_RETURN( 4097 _phy_84740_config_devid(pc->unit,pc->port, pc, &devid)); 4098 if (PHY84740_SINGLE_PORT_MODE(pc)) { 4099 if (PHY_DIAG_INTF_SYS == intf) { 4100 poly_ctrl = 0; 4101 for (lane = 0; lane < NUM_LANES; lane++) { 4102 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 4103 SOC_IF_ERROR_RETURN 4104 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4105 PHY84740_PMAD_AER_ADDR_REG, lane)); 4106 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 4107 SOC_IF_ERROR_RETURN 4108 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4109 PHY84740_USER_PRBS_CONTROL_0_REGISTER,&data16)); 4110 poly_ctrl |= (data16 & PHY84740_40G_SYS_PRBS_POLY_MASK) ; 4111 } 4112 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 4113 SOC_IF_ERROR_RETURN 4114 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4115 PHY84740_PMAD_AER_ADDR_REG, 0)); 4116 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 4117 4118 if (poly_ctrl == (PHY84740_40G_SYS_PRBS31 | 4119 (PHY84740_40G_SYS_PRBS31 << 12))) { 4120 *value = SOC_PHY_PRBS_POLYNOMIAL_X31_X28_1; 4121 } else if (poly_ctrl == (PHY84740_40G_SYS_PRBS23 | 4122 (PHY84740_40G_SYS_PRBS23 << 12))) { 4123 *value = SOC_PHY_PRBS_POLYNOMIAL_X23_X18_1; 4124 } else if (poly_ctrl == (PHY84740_40G_SYS_PRBS15 | 4125 (PHY84740_40G_SYS_PRBS15 << 12))) { 4126 *value = SOC_PHY_PRBS_POLYNOMIAL_X15_X14_1; 4127 } else if (poly_ctrl == (PHY84740_40G_SYS_PRBS11 | 4128 (PHY84740_40G_SYS_PRBS11 << 12))) { 4129 *value = SOC_PHY_PRBS_POLYNOMIAL_X11_X9_1; 4130 } else if (poly_ctrl == (PHY84740_40G_SYS_PRBS9 | 4131 (PHY84740_40G_SYS_PRBS9 << 12))) { 4132 *value = SOC_PHY_PRBS_POLYNOMIAL_X9_X5_1; 4133 } else if (poly_ctrl == (PHY84740_40G_SYS_PRBS7 | 4134 (PHY84740_40G_SYS_PRBS7 << 12))) { 4135 *value = SOC_PHY_PRBS_POLYNOMIAL_X7_X6_1; 4136 } else { 4137 return SOC_E_INTERNAL; 4138 } 4139 } else { 4140 if(PHY84740_IS_QUADRA(devid)) { 4141 SOC_IF_ERROR_RETURN 4142 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4143 PHY84740_FORTYG_SQ_WAVE_TESTING_CONTROL_REGISTER, 4144 &poly_ctrl)); 4145 poly_ctrl &= (PHY84740_40G_PRBS31 | PHY84740_40G_PRBS9); 4146 if (poly_ctrl == PHY84740_40G_PRBS31) { 4147 *value = SOC_PHY_PRBS_POLYNOMIAL_X31_X28_1; 4148 } else if (poly_ctrl == PHY84740_40G_PRBS9) { 4149 *value = SOC_PHY_PRBS_POLYNOMIAL_X9_X5_1; 4150 } else { 4151 return SOC_E_INTERNAL; 4152 } 4153 } else { 4154 SOC_IF_ERROR_RETURN 4155 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4156 PHY84740_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS, 4157 &poly_ctrl)); 4158 if (poly_ctrl & PHY84740_40G_PRBS31) { 4159 *value = 3; 4160 } else { 4161 *value = 0; /* 0 indicates PRBS9 */ 4162 } 4163 } 4164 } 4165 } else { /* quad-port mode */ 4166 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 4167 (pc->unit, pc->port, pc, &devid)); 4168 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 4169 (unit, pc, 0xc81f, &speed_val)); 4170 4171 if (PHY84740_IS_QUADRA(devid) && (speed_val & (1 << 2))) { 4172 SOC_IF_ERROR_RETURN 4173 (READ_PHY84740_MMF_AN_REG(unit, pc, 0x8019, &poly_ctrl)); 4174 *value = poly_ctrl & (uint16) 0x0003; 4175 if (*value == 1) 4176 *value = 4; 4177 if (*value == 2) 4178 *value = 5; 4179 4180 } else { 4181 SOC_IF_ERROR_RETURN 4182 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4183 PHY84740_USER_PRBS_CONTROL_0_REGISTER, 4184 &poly_ctrl)); 4185 poly_ctrl &= PHY84740_USER_PRBS_TYPE_MASK; 4186 4187 if (poly_ctrl == 1) { 4188 *value = 0; 4189 } else if (poly_ctrl == 4) { 4190 *value = 1; 4191 } else if (poly_ctrl == 5) { 4192 *value = 2; 4193 } else if (poly_ctrl == 6) { 4194 *value = 3; 4195 } else if (poly_ctrl == 2) { 4196 *value = 4; 4197 } else if (poly_ctrl == 3) { 4198 *value = 5; 4199 } else { 4200 *value = poly_ctrl; 4201 } 4202 } 4203 } 4204 4205 return SOC_E_NONE; 4206 } 4207 4208 STATIC int 4209 _phy_84740_control_prbs_tx_invert_data_get(int unit, soc_port_t port, 4210 int intf, uint32 *value) 4211 { 4212 phy_ctrl_t *pc; /* PHY software state */ 4213 uint16 data16, speed_val; 4214 uint32 devid; 4215 int lane = 0; 4216 4217 pc = EXT_PHY_SW_STATE(unit, port); 4218 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 4219 (pc->unit, pc->port, pc, &devid)); 4220 if (PHY84740_SINGLE_PORT_MODE(pc)) { 4221 if (PHY_DIAG_INTF_SYS == intf) { 4222 *value = 0; 4223 for (lane = 0; lane < NUM_LANES; lane++) { 4224 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 4225 SOC_IF_ERROR_RETURN 4226 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4227 PHY84740_PMAD_AER_ADDR_REG, lane)); 4228 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 4229 SOC_IF_ERROR_RETURN 4230 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4231 PHY84740_USER_PRBS_CONTROL_0_REGISTER,&data16)); 4232 *value |= data16 &(uint16)PHY84740_USER_PRBS_TX_INVERT; 4233 } 4234 *value >>= 4; 4235 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 4236 SOC_IF_ERROR_RETURN 4237 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4238 PHY84740_PMAD_AER_ADDR_REG, 0)); 4239 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 4240 } else { 4241 if(PHY84740_IS_QUADRA(devid)) { 4242 *value = 0; 4243 /* 4244 * In Quadra PRBS TX is inverted in PACKAGE itself, 4245 * by default bit no. 4 and bit no.3 in reg 0xcd60 is set to 4246 * 1 in this mode,which means twice inversion of PRBS TX 4247 * (means no inversion in TX) 4248 * only PRBS RX is inverted,so prbs lock won't happen,to avoid 4249 * this situation we are clearing bit no.4 in 0xcd60,means 4250 * both TX and RX inverted leads to zero prbs error. 4251 4252 * NOTE:Bit no.6 in 0xcd60 is not considered in 40G mode. 4253 * The autodetect is forced to disable. 4254 */ 4255 for (lane = 0; lane < NUM_LANES; lane++) { 4256 SOC_IF_ERROR_RETURN 4257 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4258 PHY84740_PMAD_AER_ADDR_REG, lane)); 4259 SOC_IF_ERROR_RETURN 4260 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4261 PHY84740_UDRCD_PRBS20_CONTROL_REGISTER, 4262 &data16)); 4263 *value |= data16; 4264 } 4265 *value &= PHY84740_USER_PRBS_TX_INVERT; 4266 if( *value == PHY84740_USER_PRBS_TX_INVERT) { 4267 *value = FALSE; 4268 } else { 4269 *value = TRUE; 4270 } 4271 } else { 4272 return SOC_E_UNAVAIL; 4273 } 4274 } 4275 } else { /* quad-port mode */ 4276 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 4277 (pc->unit, pc->port, pc, &devid)); 4278 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 4279 (unit, pc, 0xc81f, &speed_val)); 4280 4281 if (PHY84740_IS_QUADRA(devid) && (speed_val & (1 << 2))) { 4282 SOC_IF_ERROR_RETURN 4283 (READ_PHY84740_MMF_AN_REG(unit, pc, 0x8019, &data16)); 4284 *value = (data16 & (uint16) 0x0004) ? TRUE : FALSE; 4285 } else { 4286 SOC_IF_ERROR_RETURN 4287 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4288 PHY84740_USER_PRBS_CONTROL_0_REGISTER, 4289 &data16)); 4290 if (data16 & PHY84740_USER_PRBS_TX_INVERT) { 4291 *value = TRUE; 4292 } else { 4293 *value = FALSE; 4294 } 4295 } 4296 } 4297 return SOC_E_NONE; 4298 } 4299 4300 STATIC int 4301 _phy_84740_control_prbs_rx_status_get(int unit, soc_port_t port, 4302 int intf, uint32 *value) 4303 { 4304 phy_ctrl_t *pc; /* PHY software state */ 4305 uint16 data16, speed_val; 4306 int lane; 4307 uint32 devid; 4308 4309 pc = EXT_PHY_SW_STATE(unit, port); 4310 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 4311 (pc->unit, pc->port, pc, &devid)); 4312 *value = 0; 4313 if (PHY84740_SINGLE_PORT_MODE(pc)) { 4314 if (PHY_DIAG_INTF_SYS == intf) { 4315 for (lane = 0; lane < NUM_LANES; lane++) { 4316 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 4317 SOC_IF_ERROR_RETURN 4318 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4319 PHY84740_PMAD_AER_ADDR_REG, lane)); 4320 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 4321 SOC_IF_ERROR_RETURN 4322 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4323 PHY84740_USER_PRBS_STATUS_0_REGISTER,&data16)); 4324 if ((data16 & PHY84740_40G_SYS_PRBS_LOCK_MASK ) == 4325 PHY84740_40G_SYS_PRBS_LOCK_VALUE ) { 4326 *value += data16 & PHY84740_40G_SYS_PRBS_ERR_MASK ; 4327 } else{ 4328 *value = -1; 4329 break; 4330 } 4331 } 4332 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 4333 SOC_IF_ERROR_RETURN 4334 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4335 PHY84740_PMAD_AER_ADDR_REG, 0)); 4336 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 4337 } else { 4338 if(PHY84740_IS_QUADRA(devid)) { 4339 *value = 0; 4340 for (lane = 0; lane < 4; lane++) { 4341 SOC_IF_ERROR_RETURN 4342 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4343 PHY84740_FORTYG_PRBS_RX_TESTING_ERROR_COUNTER_LANE0 + lane, 4344 &data16)); 4345 *value |= data16; 4346 } 4347 } else { 4348 for (lane = 0; lane < 4; lane++) { 4349 SOC_IF_ERROR_RETURN 4350 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4351 PHY84740_FORTYG_PRBS_RECEIVE_ERROR_COUNTER_LANE0 4352 + lane, &data16)); 4353 if (!(data16 & 0xfff)) { 4354 /* PRBS is in sync */ 4355 continue; 4356 } else { 4357 /* Get errors */ 4358 *value += (data16 & 0xfff); 4359 } 4360 } 4361 } 4362 } 4363 } else { /* quad-port mode */ 4364 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 4365 (pc->unit, pc->port, pc, &devid)); 4366 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 4367 (unit, pc, 0xc81f, &speed_val)); 4368 if (PHY84740_IS_QUADRA(devid) && (speed_val & (1 << 2))) { 4369 data16 = 0; 4370 SOC_IF_ERROR_RETURN 4371 (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0x80b1, 0x0007)); 4372 SOC_IF_ERROR_RETURN 4373 (READ_PHY84740_MMF_AN_REG(unit, pc, 0x80b0, &data16)); 4374 if (data16 & (uint16) 0x8000) { 4375 *value = data16 & (uint16) 0x3fff; 4376 } else { 4377 *value = -1; 4378 } 4379 } else { 4380 SOC_IF_ERROR_RETURN 4381 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4382 PHY84740_USER_PRBS_STATUS_0_REGISTER, 4383 &data16)); 4384 if (data16 == 0x8000) { /* PRBS lock and error free */ 4385 *value = 0; 4386 } else if (!(data16 & 0x8000)) { 4387 *value = -1; 4388 } else { 4389 *value = data16 & 0x7fff; 4390 } 4391 } 4392 } 4393 return SOC_E_NONE; 4394 } 4395 4396 STATIC int 4397 _phy_84740_control_edc_mode_get(int unit, soc_port_t port, uint32 *value) 4398 { 4399 uint16 data16; 4400 phy_ctrl_t *pc; /* PHY software state */ 4401 4402 pc = EXT_PHY_SW_STATE(unit, port); 4403 4404 /* get EDC mode */ 4405 SOC_IF_ERROR_RETURN 4406 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1A, &data16)); 4407 4408 *value = data16 & PHY84740_EDC_MODE_MASK; 4409 4410 return SOC_E_NONE; 4411 } 4412 4413 STATIC int 4414 _phy_84740_remote_loopback_set(int unit, soc_port_t port, int intf, 4415 uint32 enable) 4416 { 4417 phy_ctrl_t *pc; /* PHY software state */ 4418 int lane; 4419 4420 pc = EXT_PHY_SW_STATE(unit, port); 4421 4422 if (intf == PHY_DIAG_INTF_SYS) { 4423 if ((PHY84740_SINGLE_PORT_MODE(pc))) { 4424 for (lane = 0; lane < NUM_LANES; lane++) { 4425 /* targeted to the system side */ 4426 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 4427 4428 SOC_IF_ERROR_RETURN 4429 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4430 PHY84740_PMAD_AER_ADDR_REG, 4431 lane)); 4432 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 4433 (unit, pc, 0xcd0a, enable ? 1 : 0, 1)); 4434 4435 /* targeted to the system side, switch back */ 4436 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 4437 } 4438 /* point back to lane0 */ 4439 SOC_IF_ERROR_RETURN 4440 (WRITE_PHY84740_MMF_PMA_PMD_REG 4441 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 4442 } else { 4443 SOC_IF_ERROR_RETURN 4444 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd0a, 4445 enable ? 1 : 0, 1)); 4446 } 4447 } 4448 return SOC_E_NONE; 4449 } 4450 4451 STATIC int _phy_84740_debug_info(int unit, soc_port_t port) 4452 { 4453 phy_ctrl_t *pc; 4454 phy_ctrl_t *int_pc; 4455 int lane; 4456 const char *if_names[] = SOC_PORT_IF_NAMES_INITIALIZER; 4457 struct dbgi { 4458 uint16 ucode_rev; 4459 uint16 pl2_reg; 4460 uint16 pma_mii_stat; 4461 uint16 tx_polarity_reg[NUM_LANES]; 4462 uint16 rx_polarity_reg[NUM_LANES]; 4463 soc_port_if_t iif; 4464 int ilink; 4465 int ispeed; 4466 int ian; 4467 int ian_done; 4468 } dbgi; 4469 4470 pc = EXT_PHY_SW_STATE(unit, port); 4471 int_pc = INT_PHY_SW_STATE(unit, port); 4472 4473 SOC_IF_ERROR_RETURN 4474 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xce00, &dbgi.ucode_rev)); 4475 4476 SOC_IF_ERROR_RETURN 4477 (READ_PHY84740_MMF_PMA_PMD_REG 4478 (unit, pc, PHY84740_PMAD_LANE0_L2P_REG, &dbgi.pl2_reg)); 4479 4480 for (lane = 0; lane < NUM_LANES; lane++) { 4481 /* point to the each lane starting at lane0 */ 4482 SOC_IF_ERROR_RETURN 4483 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4484 PHY84740_PMAD_AER_ADDR_REG, 4485 P2L_MAP(pc, lane))); 4486 4487 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 4488 (unit, pc, PHY84740_DIG_CTRL_REG, 4489 &dbgi.tx_polarity_reg[lane])); 4490 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 4491 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 4492 (unit, pc, PHY84740_DIG_CTRL_REG, 4493 &dbgi.rx_polarity_reg[lane])); 4494 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 4495 } 4496 4497 LOG_CLI((BSL_META_U(unit, 4498 "Port %-3d(mdio=0x%x): ver(1.%04x)=0x%x, single lpmode=%d, " 4499 "p2lreg(1.%04x)=0x%04x, p2lmap=%d%d%d%d\n"), 4500 port, pc->phy_id, 0xce00, dbgi.ucode_rev, 4501 SINGLE_LPMODE(pc), 4502 PHY84740_PMAD_LANE0_L2P_REG, dbgi.pl2_reg, 4503 P2L_MAP(pc, 3), P2L_MAP(pc, 2), P2L_MAP(pc, 1), P2L_MAP(pc, 4504 0))); 4505 4506 if (PHY84740_SINGLE_PORT_MODE(pc)) { 4507 SOC_IF_ERROR_RETURN 4508 (READ_PHY84740_PMA_PMD_STATr(unit, pc, &dbgi.pma_mii_stat)); 4509 SOC_IF_ERROR_RETURN(PHY_LINK_GET(int_pc->pd, unit, port, &dbgi.ilink)); 4510 LOG_CLI((BSL_META_U(unit, 4511 " pma_link(1.0x%04x)=0x%0x(%s), serdes_link=%s\n"), 4512 1, dbgi.pma_mii_stat, 4513 (dbgi.pma_mii_stat & MII_STAT_LA) ? "up" : "down", 4514 dbgi.ilink ? "up" : "down")); 4515 LOG_CLI((BSL_META_U(unit, 4516 " line polarity(1.%04x)=(ln0=%04x, " 4517 "ln1=%04x, ln2=%04x, ln3=%04x)\n"), 4518 PHY84740_DIG_CTRL_REG, dbgi.tx_polarity_reg[0], 4519 dbgi.tx_polarity_reg[1], dbgi.tx_polarity_reg[2], 4520 dbgi.tx_polarity_reg[3])); 4521 LOG_CLI((BSL_META_U(unit, 4522 " sys polarity(1.%04x)=(ln0=%04x, " 4523 "ln1=%04x, ln2=%04x, ln3=%04x)\n"), 4524 PHY84740_DIG_CTRL_REG, dbgi.rx_polarity_reg[0], 4525 dbgi.rx_polarity_reg[1], dbgi.tx_polarity_reg[2], 4526 dbgi.rx_polarity_reg[3])); 4527 } else { 4528 LOG_CLI((BSL_META_U(unit, 4529 " line polarity(1.%04x)=%04x\n"), PHY84740_DIG_CTRL_REG, 4530 dbgi.tx_polarity_reg[0])); 4531 LOG_CLI((BSL_META_U(unit, 4532 " sys polarity(1.%04x)=%04x\n"), PHY84740_DIG_CTRL_REG, 4533 dbgi.rx_polarity_reg[0])); 4534 } 4535 if (int_pc) { 4536 SOC_IF_ERROR_RETURN(PHY_INTERFACE_GET 4537 (int_pc->pd, unit, port, &dbgi.iif)); 4538 SOC_IF_ERROR_RETURN(PHY_SPEED_GET 4539 (int_pc->pd, unit, port, &dbgi.ispeed)); 4540 SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_GET 4541 (int_pc->pd, unit, port, &dbgi.ian, 4542 &dbgi.ian_done)); 4543 LOG_CLI((BSL_META_U(unit, 4544 " Internal: type=%s, speed=%d, an=%d\n"), 4545 if_names[dbgi.iif], dbgi.ispeed, dbgi.ian)); 4546 } 4547 LOG_CLI((BSL_META_U(unit, 4548 "=======\n"))); 4549 return SOC_E_NONE; 4550 } 4551 4552 /* 4553 * Function: 4554 * phy_84740_control_set 4555 * Purpose: 4556 * Configure PHY device specific control fucntion. 4557 * Parameters: 4558 * unit - StrataSwitch unit #. 4559 * port - StrataSwitch port #. 4560 * type - Control to update 4561 * value - New setting for the control 4562 * Returns: 4563 * SOC_E_NONE 4564 */ 4565 STATIC int 4566 _phy_84740_control_set(int unit, soc_port_t port, int intf, int lane, 4567 soc_phy_control_t type, uint32 value) 4568 { 4569 phy_ctrl_t *pc; /* PHY software state */ 4570 phy_ctrl_t *int_pc; 4571 int rv; 4572 uint32 devid; 4573 4574 pc = EXT_PHY_SW_STATE(unit, port); 4575 int_pc = INT_PHY_SW_STATE(unit, port); 4576 4577 PHY_CONTROL_TYPE_CHECK(type); 4578 4579 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 4580 (pc->unit, pc->port, pc, &devid)); 4581 4582 rv = SOC_E_UNAVAIL; 4583 if (intf == PHY_DIAG_INTF_SYS) { 4584 /* if is targeted to the system side */ 4585 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 4586 } 4587 switch (type) { 4588 case SOC_PHY_CONTROL_PREEMPHASIS: 4589 /* fall through */ 4590 case SOC_PHY_CONTROL_PREEMPHASIS_LANE0: 4591 /* fall through */ 4592 case SOC_PHY_CONTROL_PREEMPHASIS_LANE1: 4593 /* fall through */ 4594 case SOC_PHY_CONTROL_PREEMPHASIS_LANE2: 4595 /* fall through */ 4596 case SOC_PHY_CONTROL_PREEMPHASIS_LANE3: 4597 /* fall through */ 4598 case SOC_PHY_CONTROL_DRIVER_CURRENT: 4599 /* fall through */ 4600 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0: 4601 /* fall through */ 4602 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1: 4603 /* fall through */ 4604 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2: 4605 /* fall through */ 4606 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3: 4607 /* fall through */ 4608 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 4609 /* fall through */ 4610 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0: 4611 /* fall through */ 4612 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1: 4613 /* fall through */ 4614 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2: 4615 /* fall through */ 4616 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3: 4617 rv = _phy_84740_control_tx_driver_set(unit, port, intf, type, 4618 value); 4619 break; 4620 case SOC_PHY_CONTROL_EDC_MODE: 4621 rv = _phy_84740_control_edc_mode_set(unit, port, value); 4622 break; 4623 case SOC_PHY_CONTROL_CLOCK_ENABLE: 4624 rv = _phy_84740_control_recovery_clock_set(unit, port, value); 4625 break; 4626 case SOC_PHY_CONTROL_CLOCK_FREQUENCY: 4627 rv = _phy_84740_control_recovery_clock_freq_set(unit, port, value); 4628 break; 4629 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 4630 /* on line side, rx poly type is auto-detected. On system side, 4631 * need to enable the rx type as well. 4632 */ 4633 rv = _phy_84740_control_prbs_polynomial_set(unit, port, 4634 value, intf, 4635 TRUE); 4636 if (intf == PHY_DIAG_INTF_SYS) { 4637 rv = _phy_84740_control_prbs_polynomial_set(unit, port, value, 4638 intf, 4639 FALSE); 4640 } 4641 break; 4642 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 4643 /* on line side, rx invertion is auto-detected. On system side, 4644 * need to enable the rx as well. 4645 */ 4646 rv = _phy_84740_control_prbs_tx_invert_data_set(unit, 4647 port, 4648 intf, 4649 value); 4650 if (intf == PHY_DIAG_INTF_SYS) { 4651 rv = _phy_84740_control_prbs_rx_invert_data_set(unit, port, 4652 intf, value); 4653 } 4654 break; 4655 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 4656 /* fall through */ 4657 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 4658 /* tx/rx is enabled at the same time. no seperate control */ 4659 rv = _phy_84740_control_prbs_enable_set(unit, port, intf, value); 4660 break; 4661 case SOC_PHY_CONTROL_LOOPBACK_REMOTE: 4662 rv = _phy_84740_remote_loopback_set(unit, port, PHY_DIAG_INTF_SYS, 4663 value); 4664 break; 4665 case SOC_PHY_CONTROL_SOFTWARE_RX_LOS: 4666 if (int_pc) { 4667 SOC_IF_ERROR_RETURN 4668 (PHY_CONTROL_SET(int_pc->pd, unit, port, type, value)); 4669 SOFTWARE_RX_LOS(pc) = value ? 1 : 0; 4670 rv = SOC_E_NONE; 4671 } 4672 break; 4673 case SOC_PHY_CONTROL_DUMP: 4674 rv = _phy_84740_debug_info(unit, port); 4675 break; 4676 case SOC_PHY_CONTROL_TX_POLARITY: 4677 if (PHY84740_IS_QUADRA(devid)) { /* Quadra */ 4678 rv = phy_84740_tx_polarity_flip_set(unit, port, value); 4679 } else { 4680 rv = SOC_E_UNAVAIL; 4681 } 4682 break; 4683 case SOC_PHY_CONTROL_RX_POLARITY: 4684 if (PHY84740_IS_QUADRA(devid)) { /* Quadra */ 4685 rv = phy_84740_rx_polarity_flip_set(unit, port, value); 4686 } else { 4687 rv = SOC_E_UNAVAIL; 4688 } 4689 break; 4690 case SOC_PHY_CONTROL_TX_LANE_SQUELCH: 4691 /* inside the _phy_84740_squelch_enable function, check for Quadra */ 4692 rv = _phy_84740_squelch_enable(unit, port, intf, value, FALSE); 4693 break; 4694 default: 4695 rv = SOC_E_UNAVAIL; 4696 break; 4697 } 4698 if (intf == PHY_DIAG_INTF_SYS) { 4699 /* if it is targeted to the system side, switch back */ 4700 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 4701 } 4702 return rv; 4703 } 4704 4705 STATIC int phy_84740_tx_polarity_flip_set(int unit, int port, uint32 value) 4706 { 4707 int lane; 4708 phy_ctrl_t *pc; 4709 uint16 tx_pol; 4710 uint16 data16, mask16; 4711 4712 pc = EXT_PHY_SW_STATE(unit, port); 4713 tx_pol = value; 4714 4715 /* get the reset default value. The 84740 device has the TX polarity flipped 4716 * by default. Construct the init default value 4717 */ 4718 4719 mask16 = PHY84740_TX_POLARITY_FLIP_MASK; 4720 4721 if ((PHY84740_SINGLE_PORT_MODE(pc))) { 4722 for (lane = 0; lane < NUM_LANES; lane++) { 4723 data16 = 0; 4724 4725 /* point to the each lane starting at lane0 */ 4726 SOC_IF_ERROR_RETURN 4727 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4728 PHY84740_PMAD_AER_ADDR_REG, 4729 P2L_MAP(pc, lane))); 4730 4731 if ((tx_pol == POL_CONFIG_ALL_LANES) || 4732 ((tx_pol & POL_CONFIG_LANE_MASK(lane)) == 4733 POL_CONFIG_LANE_MASK(lane))) { 4734 data16 = PHY84740_TX_POLARITY_FLIP_MASK; 4735 } 4736 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4737 PHY84740_DIG_CTRL_REG, 4738 data16, 4739 mask16)); 4740 } 4741 /* point back to lane0 */ 4742 SOC_IF_ERROR_RETURN 4743 (WRITE_PHY84740_MMF_PMA_PMD_REG 4744 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 4745 } else { /* quad-port mode */ 4746 data16 = 0; 4747 tx_pol = PHY84740_10G_POL_CFG_GET(pc, tx_pol); 4748 if (tx_pol) { 4749 data16 = PHY84740_TX_POLARITY_FLIP_MASK; 4750 } 4751 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 4752 (unit, pc, PHY84740_DIG_CTRL_REG, data16, mask16)); 4753 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 4754 (unit, pc, PHY84740_DIG_CTRL_REG, &data16)); 4755 } 4756 4757 return SOC_E_NONE; 4758 } 4759 4760 STATIC int phy_84740_rx_polarity_flip_set(int unit, int port, uint32 value) 4761 { 4762 int lane; 4763 phy_ctrl_t *pc; 4764 uint16 rx_pol; 4765 uint16 data16, mask16; 4766 4767 pc = EXT_PHY_SW_STATE(unit, port); 4768 4769 rx_pol = value; 4770 /* get the reset default value. The 84740 device has the TX polarity flipped 4771 * by default. Construct the init default value 4772 */ 4773 mask16 = PHY84740_RX_POLARITY_FLIP_MASK; 4774 4775 if ((PHY84740_SINGLE_PORT_MODE(pc))) { 4776 for (lane = 0; lane < NUM_LANES; lane++) { 4777 data16 = 0; 4778 4779 /* point to the each lane starting at lane0 */ 4780 SOC_IF_ERROR_RETURN 4781 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4782 PHY84740_PMAD_AER_ADDR_REG, 4783 P2L_MAP(pc, lane))); 4784 if ((rx_pol == POL_CONFIG_ALL_LANES) 4785 || ((rx_pol & POL_CONFIG_LANE_MASK(lane)) == 4786 POL_CONFIG_LANE_MASK(lane))) { 4787 data16 |= PHY84740_RX_POLARITY_FLIP_MASK; 4788 } 4789 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 4790 PHY84740_DIG_CTRL_REG, 4791 data16, 4792 mask16)); 4793 } 4794 /* point back to lane0 */ 4795 SOC_IF_ERROR_RETURN 4796 (WRITE_PHY84740_MMF_PMA_PMD_REG 4797 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 4798 } else { /* quad-port mode */ 4799 data16 = 0; 4800 rx_pol = PHY84740_10G_POL_CFG_GET(pc, rx_pol); 4801 if (rx_pol) { 4802 data16 = PHY84740_RX_POLARITY_FLIP_MASK; 4803 } 4804 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 4805 (unit, pc, PHY84740_DIG_CTRL_REG, data16, mask16)); 4806 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 4807 (unit, pc, PHY84740_DIG_CTRL_REG, &data16)); 4808 } 4809 return SOC_E_NONE; 4810 } 4811 4812 STATIC int 4813 phy_84740_control_set(int unit, soc_port_t port, 4814 soc_phy_control_t type, uint32 value) 4815 { 4816 phy_ctrl_t *pc; /* PHY software state */ 4817 int intf; 4818 4819 pc = EXT_PHY_SW_STATE(unit, port); 4820 4821 intf = (REVERSE_MODE(pc) || (pc->flags & PHYCTRL_SYS_SIDE_CTRL)) ? 4822 PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE; 4823 SOC_IF_ERROR_RETURN 4824 (_phy_84740_control_set(unit, port, intf, 4825 PHY_DIAG_LN_DFLT, type, value)); 4826 return SOC_E_NONE; 4827 } 4828 4829 /* 4830 * Function: 4831 * phy_84740_control_get 4832 * Purpose: 4833 * Get current control settign of the PHY. 4834 * Parameters: 4835 * unit - StrataSwitch unit #. 4836 * port - StrataSwitch port #. 4837 * type - Control to update 4838 * value - (OUT)Current setting for the control 4839 * Returns: 4840 * SOC_E_NONE 4841 */ 4842 STATIC int 4843 _phy_84740_control_get(int unit, soc_port_t port, int intf, int lane, 4844 soc_phy_control_t type, uint32 *value) 4845 { 4846 phy_ctrl_t *pc; /* PHY software state */ 4847 int rv; 4848 uint16 data16; 4849 4850 pc = EXT_PHY_SW_STATE(unit, port); 4851 4852 PHY_CONTROL_TYPE_CHECK(type); 4853 4854 if (intf == PHY_DIAG_INTF_SYS) { 4855 /* targeted to the system side */ 4856 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 4857 } 4858 rv = SOC_E_UNAVAIL; 4859 switch (type) { 4860 case SOC_PHY_CONTROL_PREEMPHASIS: 4861 /* fall through */ 4862 case SOC_PHY_CONTROL_PREEMPHASIS_LANE0: 4863 /* fall through */ 4864 case SOC_PHY_CONTROL_PREEMPHASIS_LANE1: 4865 /* fall through */ 4866 case SOC_PHY_CONTROL_PREEMPHASIS_LANE2: 4867 /* fall through */ 4868 case SOC_PHY_CONTROL_PREEMPHASIS_LANE3: 4869 /* fall through */ 4870 case SOC_PHY_CONTROL_DRIVER_CURRENT: 4871 /* fall through */ 4872 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0: 4873 /* fall through */ 4874 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1: 4875 /* fall through */ 4876 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2: 4877 /* fall through */ 4878 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3: 4879 /* fall through */ 4880 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 4881 /* fall through */ 4882 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0: 4883 /* fall through */ 4884 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1: 4885 /* fall through */ 4886 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2: 4887 /* fall through */ 4888 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3: 4889 rv = _phy_84740_control_tx_driver_get(unit, port, intf, type, 4890 value); 4891 break; 4892 case SOC_PHY_CONTROL_EDC_MODE: 4893 rv = _phy_84740_control_edc_mode_get(unit, port, value); 4894 break; 4895 case SOC_PHY_CONTROL_CLOCK_ENABLE: 4896 SOC_IF_ERROR_RETURN 4897 (READ_PHY84740_MMF_PMA_PMD_REG 4898 (unit, pc, PHY84740_PMAD_RECOVERY_CLK_REG, &data16)); 4899 *value = 4900 (data16 & PHY84740_RECOVERY_CLK_ENABLE_MASK) ? TRUE : FALSE; 4901 rv = SOC_E_NONE; 4902 break; 4903 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 4904 rv = _phy_84740_control_prbs_polynomial_get(unit, 4905 port, 4906 intf, 4907 value); 4908 break; 4909 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 4910 rv = _phy_84740_control_prbs_tx_invert_data_get(unit, 4911 port, 4912 intf, 4913 value); 4914 break; 4915 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 4916 /* fall through */ 4917 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 4918 rv = _phy_84740_control_prbs_enable_get(unit, port, intf, value); 4919 break; 4920 case SOC_PHY_CONTROL_PRBS_RX_STATUS: 4921 rv = _phy_84740_control_prbs_rx_status_get(unit, port, intf, value); 4922 break; 4923 case SOC_PHY_CONTROL_CLOCK_FREQUENCY: 4924 SOC_IF_ERROR_RETURN 4925 (READ_PHY84740_MMF_PMA_PMD_REG 4926 (unit, pc, PHY84740_PMAD_RECOVERY_CLK_FREQ_REG, &data16)); 4927 switch ((data16 >> PHY84740_RECOVERY_CLK_FREQ_SHIFT) & 0x3) { 4928 case 0x1: 4929 *value = 125000; 4930 break; 4931 case 0x2: 4932 *value = 195312; 4933 break; 4934 case 0x3: 4935 *value = 156250; 4936 break; 4937 default: 4938 *value = 0x0; 4939 break; 4940 } 4941 rv = SOC_E_NONE; 4942 break; 4943 case SOC_PHY_CONTROL_SOFTWARE_RX_LOS: 4944 *value = SOFTWARE_RX_LOS(pc); 4945 rv = SOC_E_NONE; 4946 break; 4947 4948 default: 4949 rv = SOC_E_UNAVAIL; 4950 break; 4951 } 4952 4953 if (intf == PHY_DIAG_INTF_SYS) { 4954 /* if it is targeted to the system side, switch back */ 4955 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 4956 } 4957 return rv; 4958 } 4959 4960 STATIC int 4961 phy_84740_control_get(int unit, soc_port_t port, 4962 soc_phy_control_t type, uint32 *value) 4963 { 4964 int intf; 4965 phy_ctrl_t *pc; /* PHY software state */ 4966 4967 pc = EXT_PHY_SW_STATE(unit, port); 4968 4969 intf = (REVERSE_MODE(pc) || (pc->flags & PHYCTRL_SYS_SIDE_CTRL)) ? 4970 PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE; 4971 4972 SOC_IF_ERROR_RETURN 4973 (_phy_84740_control_get(unit, port, intf, 4974 PHY_DIAG_LN_DFLT, type, value)); 4975 return SOC_E_NONE; 4976 } 4977 4978 STATIC int phy_84740_diag_ctrl(int unit, /* unit */ 4979 soc_port_t port, /* port */ 4980 uint32 inst, /* the specific device block the control action directs to */ 4981 int op_type, /* operation types: read,write or command sequence */ 4982 int op_cmd, /* command code */ 4983 void *arg) 4984 { /* command argument */ 4985 int lane; 4986 int intf; 4987 4988 LOG_INFO(BSL_LS_SOC_PHY, 4989 (BSL_META_U(unit, 4990 "phy_84740_diag_ctrl: u=%d p=%d ctrl=0x%x\n"), 4991 unit, port, op_cmd)); 4992 4993 lane = PHY_DIAG_INST_LN(inst); 4994 intf = PHY_DIAG_INST_INTF(inst); 4995 if (intf == PHY_DIAG_INTF_DFLT) { 4996 intf = PHY_DIAG_INTF_LINE; 4997 } 4998 4999 if (op_type == PHY_DIAG_CTRL_GET) { 5000 SOC_IF_ERROR_RETURN 5001 (_phy_84740_control_get(unit, port, intf, lane, 5002 op_cmd, (uint32 *) arg)); 5003 } else if (op_type == PHY_DIAG_CTRL_SET) { 5004 SOC_IF_ERROR_RETURN 5005 (_phy_84740_control_set(unit, port, intf, lane, 5006 op_cmd, PTR_TO_INT(arg))); 5007 } 5008 return SOC_E_NONE; 5009 } 5010 5011 /* 5012 * Function: 5013 * phy_84740_speed_set 5014 * Purpose: 5015 * Set PHY speed 5016 * Parameters: 5017 * unit - StrataSwitch unit #. 5018 * port - StrataSwitch port #. 5019 * speed - link speed in Mbps 5020 * Returns: 5021 * SOC_E_NONE 5022 */ 5023 5024 STATIC int phy_84740_speed_set(int unit, soc_port_t port, int speed) 5025 { 5026 phy_ctrl_t *pc; 5027 phy_ctrl_t *int_pc; 5028 int rv = SOC_E_NONE; 5029 5030 COMPILER_REFERENCE(unit); 5031 COMPILER_REFERENCE(port); 5032 5033 int_pc = INT_PHY_SW_STATE(unit, port); 5034 pc = EXT_PHY_SW_STATE(unit, port); 5035 5036 LOG_INFO(BSL_LS_SOC_PHY, 5037 (BSL_META_U(unit, 5038 "phy_84740_speed_set: u=%d p=%d speed=%d\n"), 5039 unit, port, speed)); 5040 5041 if (FCMAP_PASSTHROUGH(pc)) { 5042 return SOC_E_NONE; 5043 } 5044 5045 if (PHY84740_SINGLE_PORT_MODE(pc)) { 5046 if (speed != 40000) { 5047 return SOC_E_PARAM; 5048 } 5049 5050 /* single port mode: doesn't use PCS. should be already in repeater mode */ 5051 /* it is always in 40G speed, make sure internal device is in 40G */ 5052 if (NULL != int_pc) { 5053 if (REVERSE_MODE(pc)) { 5054 if (IS_HG_PORT(unit, port)) { 5055 SOC_IF_ERROR_RETURN 5056 (PHY_INTERFACE_SET 5057 (int_pc->pd, unit, port, SOC_PORT_IF_KR4)); 5058 } else { 5059 SOC_IF_ERROR_RETURN 5060 (PHY_INTERFACE_SET 5061 (int_pc->pd, unit, port, SOC_PORT_IF_SR4)); 5062 } 5063 } else { 5064 if (soc_property_port_get(unit, port, spn_PHY_LONG_XFI, 0)) { 5065 rv = PHY_INTERFACE_SET(int_pc->pd, unit, port, 5066 SOC_PORT_IF_CR); 5067 } 5068 } 5069 5070 rv = PHY_SPEED_SET(int_pc->pd, unit, port, speed); 5071 } 5072 return rv; 5073 } 5074 5075 /* quad lane mode */ 5076 if ((!(speed == 10000 || speed == 1000)) && (!PCS_REPEATER(pc))) { 5077 return SOC_E_PARAM; 5078 } 5079 5080 if (speed == 10000) { 5081 SOC_IF_ERROR_RETURN 5082 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CTRL_REG, 5083 MII_CTRL_SS_MSB | MII_CTRL_SS_LSB, 5084 MII_CTRL_SS_MSB | MII_CTRL_SS_LSB)); 5085 SOC_IF_ERROR_RETURN 5086 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CTRL2_REG, 5087 PHY84740_PMAD_CTRL2r_PMA_TYPE_10G_LRM, 5088 PHY84740_PMAD_CTRL2r_PMA_TYPE_MASK)); 5089 5090 } else { 5091 SOC_IF_ERROR_RETURN 5092 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CTRL2_REG, 5093 PHY84740_PMAD_CTRL2r_PMA_TYPE_1G_KX, 5094 PHY84740_PMAD_CTRL2r_PMA_TYPE_MASK)); 5095 SOC_IF_ERROR_RETURN 5096 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, MII_CTRL_REG, 5097 0, MII_CTRL_SS_LSB)); 5098 } 5099 /* need to set the internal phy's speed accordingly */ 5100 5101 if (NULL != int_pc) { 5102 if (REVERSE_MODE(pc)) { 5103 SOC_IF_ERROR_RETURN 5104 (PHY_INTERFACE_SET(int_pc->pd, unit, port, SOC_PORT_IF_SR)); 5105 } else { 5106 /* For long XFI channel, it is best to use SFP+ DAC mode 5107 * in the serdes side to provide adequate Rx equalization 5108 */ 5109 if (soc_property_port_get(unit, port, spn_PHY_LONG_XFI, 0)) { 5110 if (!PHY84740_SINGLE_PORT_MODE(pc)) { 5111 rv = PHY_INTERFACE_SET(int_pc->pd, unit, port, 5112 SOC_PORT_IF_CR); 5113 } 5114 } 5115 } 5116 rv = PHY_SPEED_SET(int_pc->pd, unit, port, speed); 5117 } 5118 return rv; 5119 } 5120 5121 /* 5122 * Function: 5123 * phy_84740_speed_get 5124 * Purpose: 5125 * Get PHY speed 5126 * Parameters: 5127 * unit - StrataSwitch unit #. 5128 * port - StrataSwitch port #. 5129 * speed - current link speed in Mbps 5130 * Returns: 5131 * SOC_E_NONE 5132 */ 5133 5134 STATIC int phy_84740_speed_get(int unit, soc_port_t port, int *speed) 5135 { 5136 phy_ctrl_t *pc; 5137 uint16 speed_val; 5138 5139 pc = EXT_PHY_SW_STATE(unit, port); 5140 5141 if (PCS_REPEATER(pc)) { 5142 phy_ctrl_t *int_pc; 5143 5144 int_pc = INT_PHY_SW_STATE(unit, port); 5145 SOC_IF_ERROR_RETURN(PHY_SPEED_GET(int_pc->pd, unit, port, speed)); 5146 return SOC_E_NONE; 5147 } else if (FCMAP_PASSTHROUGH(pc)) { 5148 *speed = 10000; 5149 return SOC_E_NONE; 5150 } 5151 5152 /* this register contains the speed info for both single/quad modes */ 5153 SOC_IF_ERROR_RETURN 5154 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81f, &speed_val)); 5155 5156 if (speed_val & (1 << 5)) { 5157 *speed = 40000; 5158 } else if (speed_val & (1 << 4)) { 5159 *speed = 10000; 5160 } else if (speed_val & (1 << 2)) { 5161 *speed = 1000; 5162 } else { /* default */ 5163 if (PHY84740_SINGLE_PORT_MODE(pc)) { 5164 *speed = 40000; 5165 } else { 5166 *speed = 10000; 5167 } 5168 } 5169 return SOC_E_NONE; 5170 } 5171 5172 /* 5173 * Function: 5174 * phy_84740_interface_set 5175 * Purpose: 5176 * Set either CR4 interface or SR4/LR4. The valid interface are SOC_PORT_IF_CR4 5177 * and SOC_PORT_IF_XLAUI which put device in default mode: SR4/LR4 mode 5178 * Parameters: 5179 * unit - StrataSwitch unit #. 5180 * port - StrataSwitch port #. 5181 * pif - one of SOC_PORT_IF_* 5182 * Returns: 5183 * SOC_E_NONE - success 5184 * SOC_E_UNAVAIL - unsupported interface 5185 */ 5186 5187 STATIC int phy_84740_interface_set(int unit, soc_port_t port, soc_port_if_t pif) 5188 { 5189 phy_ctrl_t *pc; 5190 phy_ctrl_t *int_pc; 5191 uint16 ucode_ver; 5192 uint16 sig_lvl_reg[4]; 5193 uint16 rxlos_reg[4]; 5194 uint16 pol_reg[4]; 5195 int lane; 5196 uint32 devid; 5197 soc_port_ability_t ability; 5198 5199 int_pc = INT_PHY_SW_STATE(unit, port); 5200 pc = EXT_PHY_SW_STATE(unit, port); 5201 5202 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 5203 (pc->unit, pc->port, pc, &devid)); 5204 5205 if (int_pc != NULL) { 5206 if (REVERSE_MODE(pc)) { 5207 SOC_IF_ERROR_RETURN(PHY_INTERFACE_SET(int_pc->pd, unit, port, pif)); 5208 SOC_IF_ERROR_RETURN(PHY_ABILITY_ADVERT_GET 5209 (int_pc->pd, unit, port, &ability)); 5210 SOC_IF_ERROR_RETURN(PHY_ABILITY_ADVERT_SET 5211 (int_pc->pd, unit, port, &ability)); 5212 } 5213 } 5214 5215 if (PHY84740_IS_QUADRA(devid)) { /* Quadra */ 5216 if (!(PHY84740_SINGLE_PORT_MODE(pc))) { /*1G/10G mode */ 5217 switch (pif) { 5218 case SOC_PORT_IF_CR: 5219 SOC_IF_ERROR_RETURN 5220 (MODIFY_PHY84740_MMF_PMA_PMD_REG 5221 (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 5222 PHY84740_PMAD_DAC_MODE_MASK, 5223 PHY84740_PMAD_DAC_MODE_MASK)); 5224 break; 5225 case SOC_PORT_IF_SR: 5226 case SOC_PORT_IF_LR: 5227 case SOC_PORT_IF_XAUI: 5228 SOC_IF_ERROR_RETURN 5229 (MODIFY_PHY84740_MMF_PMA_PMD_REG 5230 (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 0, 5231 PHY84740_PMAD_DAC_MODE_MASK)); 5232 break; 5233 default: 5234 break; 5235 } 5236 } else { /* 40G mode */ 5237 switch (pif) { 5238 case SOC_PORT_IF_CR4: 5239 SOC_IF_ERROR_RETURN 5240 (MODIFY_PHY84740_MMF_PMA_PMD_REG 5241 (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 5242 PHY84740_PMAD_DAC_MODE_MASK, 5243 PHY84740_PMAD_DAC_MODE_MASK)); 5244 break; 5245 case SOC_PORT_IF_SR4: 5246 case SOC_PORT_IF_LR4: 5247 case SOC_PORT_IF_XLAUI: 5248 SOC_IF_ERROR_RETURN 5249 (MODIFY_PHY84740_MMF_PMA_PMD_REG 5250 (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 0, 5251 PHY84740_PMAD_DAC_MODE_MASK)); 5252 break; 5253 default: 5254 break; 5255 } 5256 } 5257 } else { /* Quebec */ 5258 if (!(PHY84740_SINGLE_PORT_MODE(pc))) { /*1G/10G mode */ 5259 return phy_null_interface_set(unit, port, pif); 5260 } else { /* 40G mode */ 5261 switch (pif) { 5262 case SOC_PORT_IF_CR4: 5263 SOC_IF_ERROR_RETURN 5264 (MODIFY_PHY84740_MMF_PMA_PMD_REG 5265 (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 5266 PHY84740_PMAD_DAC_MODE_MASK, 5267 PHY84740_PMAD_DAC_MODE_MASK)); 5268 break; 5269 5270 case SOC_PORT_IF_XLAUI: 5271 SOC_IF_ERROR_RETURN 5272 (MODIFY_PHY84740_MMF_PMA_PMD_REG 5273 (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 0, 5274 PHY84740_PMAD_DAC_MODE_MASK)); 5275 break; 5276 default: 5277 break; 5278 } 5279 } 5280 } 5281 5282 SOC_IF_ERROR_RETURN 5283 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xce00, &ucode_ver)); 5284 5285 if (ucode_ver >= 0x0104) { 5286 /* For 40G mode, Do not reset the PHY if ucode is D104 on newer */ 5287 return SOC_E_NONE; 5288 } 5289 5290 /* After switching mode, user need to redo the configuration */ 5291 if (pif == SOC_PORT_IF_CR4 || pif == SOC_PORT_IF_XLAUI) { 5292 5293 /* save the register settings */ 5294 for (lane = 0; lane < NUM_LANES; lane++) { 5295 /* point to the each lane starting at lane0 */ 5296 SOC_IF_ERROR_RETURN 5297 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 5298 PHY84740_PMAD_AER_ADDR_REG, 5299 lane)); 5300 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 5301 (unit, pc, PHY84740_DIG_CTRL_REG, 5302 &pol_reg[lane])); 5303 5304 SOC_IF_ERROR_RETURN 5305 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 5306 PHY84740_PMAD_OPTICAL_CFG_REG, 5307 &rxlos_reg[lane])); 5308 SOC_IF_ERROR_RETURN 5309 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 5310 PHY84740_PMAD_OPTICAL_SIG_LVL_REG, 5311 &sig_lvl_reg[lane])); 5312 } 5313 5314 /* perform IEEE reset */ 5315 SOC_IF_ERROR_RETURN 5316 (MODIFY_PHY84740_PMA_PMD_CTRLr(pc->unit, pc, 5317 MII_CTRL_RESET, MII_CTRL_RESET)); 5318 5319 sal_udelay(100); /* Wait for 100us */ 5320 5321 /* restore back saved register values */ 5322 for (lane = 0; lane < NUM_LANES; lane++) { 5323 /* point to the each lane starting at lane0 */ 5324 SOC_IF_ERROR_RETURN 5325 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 5326 PHY84740_PMAD_AER_ADDR_REG, 5327 lane)); 5328 SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG 5329 (unit, pc, PHY84740_DIG_CTRL_REG, 5330 pol_reg[lane])); 5331 5332 SOC_IF_ERROR_RETURN 5333 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 5334 PHY84740_PMAD_OPTICAL_CFG_REG, 5335 rxlos_reg[lane])); 5336 SOC_IF_ERROR_RETURN 5337 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 5338 PHY84740_PMAD_OPTICAL_SIG_LVL_REG, 5339 sig_lvl_reg[lane])); 5340 } 5341 5342 /* redo Polarity configuration */ 5343 SOC_IF_ERROR_RETURN(_phy_84740_polarity_flip_set(unit, port)); 5344 5345 /* point back to lane0 */ 5346 SOC_IF_ERROR_RETURN 5347 (WRITE_PHY84740_MMF_PMA_PMD_REG 5348 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 5349 } 5350 5351 return SOC_E_NONE; 5352 } 5353 5354 /* 5355 * Function: 5356 * phy_84740_interface_get 5357 * Purpose: 5358 * Get the current operating mode of the PHY. 5359 * Parameters: 5360 * unit - StrataSwitch unit #. 5361 * port - StrataSwitch port #. 5362 * pif - (OUT) one of SOC_PORT_IF_* 5363 * Returns: 5364 * SOC_E_NONE 5365 */ 5366 5367 STATIC int 5368 phy_84740_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 5369 { 5370 phy_ctrl_t *pc; 5371 uint16 mode; 5372 uint16 speed_val; 5373 uint32 devid; 5374 5375 pc = EXT_PHY_SW_STATE(unit, port); 5376 5377 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 5378 (pc->unit, pc->port, pc, &devid)); 5379 5380 SOC_IF_ERROR_RETURN 5381 (READ_PHY84740_MMF_PMA_PMD_REG 5382 (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, &mode)); 5383 5384 if (PHY84740_IS_QUADRA(devid)) { 5385 if (!(PHY84740_SINGLE_PORT_MODE(pc))) { /*10G mode */ 5386 if (mode & PHY84740_PMAD_DAC_MODE_MASK) { 5387 *pif = SOC_PORT_IF_CR; 5388 } else if (mode & PHY84740_PMAD_BKPLANE_MODE_MASK) { 5389 SOC_IF_ERROR_RETURN 5390 (READ_PHY84740_MMF_PMA_PMD_REG 5391 (unit, pc, 0xc81f, &speed_val)); 5392 if ((speed_val & (1 << 2))) { /*10G/1G mode */ 5393 *pif = SOC_PORT_IF_KX; 5394 } else { 5395 *pif = SOC_PORT_IF_KR; 5396 } 5397 } else { 5398 *pif = SOC_PORT_IF_XAUI; 5399 } 5400 } else { /*40G mode */ 5401 if (mode & PHY84740_PMAD_DAC_MODE_MASK) { 5402 *pif = SOC_PORT_IF_CR4; 5403 } else if (mode & PHY84740_PMAD_BKPLANE_MODE_MASK) { 5404 *pif = SOC_PORT_IF_KR4; 5405 } else { 5406 *pif = SOC_PORT_IF_XLAUI; 5407 } 5408 } 5409 } else { /*Quebec */ 5410 if (!(PHY84740_SINGLE_PORT_MODE(pc))) { 5411 *pif = SOC_PORT_IF_XAUI; 5412 } else { /*40G mode */ 5413 if (mode & PHY84740_PMAD_DAC_MODE_MASK) { 5414 *pif = SOC_PORT_IF_CR4; 5415 } else { 5416 *pif = SOC_PORT_IF_XLAUI; 5417 } 5418 } 5419 } 5420 return SOC_E_NONE; 5421 } 5422 5423 /* 5424 * Function: * phy_84740_rom_wait 5425 * 5426 * Purpose: 5427 * Wait for data to be written to the SPI-ROM. 5428 * Input: 5429 * unit, port 5430 */ 5431 STATIC int phy_84740_rom_wait(int unit, int port) 5432 { 5433 uint16 rd_data; 5434 uint16 wr_data; 5435 uint16 data16; 5436 int count; 5437 phy_ctrl_t *pc; 5438 soc_timeout_t to; 5439 int SPI_READY; 5440 5441 pc = EXT_PHY_SW_STATE(unit, port); 5442 5443 rd_data = 0; 5444 soc_timeout_init(&to, WR_TIMEOUT, 0); 5445 do { 5446 /* Write SPI Control Register Read Command. */ 5447 count = 1; 5448 wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count); 5449 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5450 wr_data = SPI_CTRL_1_L; 5451 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5452 5453 /* extra reads to clear the status */ 5454 SOC_IF_ERROR_RETURN 5455 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16)); 5456 SOC_IF_ERROR_RETURN 5457 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16)); 5458 5459 if (rd_data & 0x0100) { 5460 break; 5461 } 5462 } while (!soc_timeout_check(&to)); 5463 if (!(rd_data & 0x0100)) { 5464 LOG_ERROR(BSL_LS_SOC_PHY, 5465 (BSL_META_U(unit, 5466 "phy_84740_rom_program: u = %d p = %d " 5467 "timeout 1\n"), unit, port)); 5468 return SOC_E_TIMEOUT; 5469 } 5470 5471 SPI_READY = 1; 5472 while (SPI_READY == 1) { 5473 /* Set-up SPI Controller To Receive SPI EEPROM Status. */ 5474 count = 1; 5475 wr_data = ((WR_CPU_CTRL_REGS * 0x0100) | count); 5476 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5477 wr_data = SPI_CTRL_2_H; 5478 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5479 wr_data = 0x0100; 5480 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5481 /* Fill-up SPI Transmit Fifo To check SPI Status. */ 5482 count = 2; 5483 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 5484 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5485 /* Write Tx Fifo Register Address. */ 5486 wr_data = SPI_TXFIFO; 5487 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5488 5489 /* Write SPI Tx Fifo Control Word-1. */ 5490 wr_data = ((1 * 0x0100) | MSGTYPE_HRD); 5491 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5492 /* Write SPI Tx Fifo Control Word-2. */ 5493 wr_data = RDSR_OPCODE; 5494 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5495 /* Write SPI Control Register Write Command. */ 5496 count = 2; 5497 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 5498 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5499 /* Write SPI Control -1 Register Address. */ 5500 wr_data = SPI_CTRL_1_L; 5501 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5502 /* Write SPI Control -1 Register Word-1. */ 5503 wr_data = 0x0101; 5504 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5505 /* Write SPI Control -1 Register Word-2. */ 5506 wr_data = 0x0100; 5507 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5508 /* Write SPI Control Register Write Command. */ 5509 count = 1; 5510 wr_data = ((WR_CPU_CTRL_REGS * 0x0100) | count); 5511 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5512 /* Write SPI Control -1 Register Address. */ 5513 wr_data = SPI_CTRL_1_H; 5514 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5515 /* Write SPI Control -1 Register Word-2. */ 5516 wr_data = 0x0103; 5517 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5518 /* Wait For 64 bytes To be written. */ 5519 rd_data = 0x0000; 5520 soc_timeout_init(&to, WR_TIMEOUT, 0); 5521 do { 5522 count = 1; 5523 wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count); 5524 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5525 wr_data = SPI_CTRL_1_L; 5526 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5527 5528 /* extra reads to clear the status */ 5529 SOC_IF_ERROR_RETURN 5530 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16)); 5531 SOC_IF_ERROR_RETURN 5532 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16)); 5533 5534 if (rd_data & 0x0100) { 5535 break; 5536 } 5537 } while (!soc_timeout_check(&to)); 5538 if (!(rd_data & 0x0100)) { 5539 LOG_ERROR(BSL_LS_SOC_PHY, 5540 (BSL_META_U(unit, 5541 "phy_84740_rom_program: u = %d p = %d " 5542 "timeout 2\n"), unit, port)); 5543 return SOC_E_TIMEOUT; 5544 } 5545 /* Write SPI Control Register Read Command. */ 5546 count = 1; 5547 wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count); 5548 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5549 /* Write SPI Control -1 Register Address. */ 5550 wr_data = SPI_RXFIFO; 5551 5552 SOC_IF_ERROR_RETURN 5553 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA12, wr_data)); 5554 SOC_IF_ERROR_RETURN 5555 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &rd_data)); 5556 5557 /* Clear LASI Message Out Status. */ 5558 SOC_IF_ERROR_RETURN 5559 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &wr_data)); 5560 5561 if ((rd_data & 0x1) == 0) { 5562 SPI_READY = 0; 5563 } 5564 /* extra reads to clear the status */ 5565 SOC_IF_ERROR_RETURN 5566 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16)); 5567 SOC_IF_ERROR_RETURN 5568 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16)); 5569 } /* SPI_READY */ 5570 return SOC_E_NONE; 5571 } 5572 5573 /* 5574 * Function: 5575 * phy_84740_rom_write_enable_set 5576 * 5577 * Purpose: 5578 * Enable disable protection on SPI_EEPROM 5579 * 5580 * Input: 5581 * unit 5582 * port 5583 * enable 5584 * Output: 5585 * SOC_E_xxx 5586 * 5587 * Notes: 5588 * 25AA256 256Kbit Serial EEPROM 5589 * STATUS Register 5590 * +------------------------------------------+ 5591 * | WPEN | x | x | x | BP1 | BP0 | WEL | WIP | 5592 * +------------------------------------------+ 5593 * BP1 BP0 : Protected Blocks 5594 * 0 0 : Protect None 5595 * 1 1 : Protect All 5596 * 5597 * WEL : Write Latch Enable 5598 * 0 : Do not allow writes 5599 * 1 : Allow writes 5600 */ 5601 5602 STATIC int 5603 phy_84740_rom_write_enable_set(int unit, int port, int enable) 5604 { 5605 uint16 rd_data; 5606 uint16 wr_data; 5607 uint8 wrsr_data; 5608 int count; 5609 phy_ctrl_t *pc; 5610 5611 pc = EXT_PHY_SW_STATE(unit, port); 5612 5613 /* 5614 * Write SPI Control Register Write Command. 5615 */ 5616 count = 2; 5617 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 5618 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5619 5620 /* 5621 * Write SPI Control -2 Register Address. 5622 */ 5623 wr_data = SPI_CTRL_2_L; 5624 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5625 5626 /* 5627 * Write SPI Control -2 Register Word-1. 5628 */ 5629 wr_data = 0x8200; 5630 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5631 5632 /* 5633 * Write SPI Control -2 Register Word-2. 5634 */ 5635 wr_data = 0x0100; 5636 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5637 5638 /* 5639 * Fill-up SPI Transmit Fifo With SPI EEPROM Messages. 5640 * Write SPI Control Register Write Command. 5641 */ 5642 count = 4; 5643 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 5644 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5645 5646 /* 5647 * Write Tx Fifo Register Address. 5648 */ 5649 wr_data = SPI_TXFIFO; 5650 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5651 5652 /* 5653 * Write SPI Tx Fifo Control Word-1. 5654 */ 5655 wr_data = ((1 * 0x0100) | MSGTYPE_HWR); 5656 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5657 5658 /* 5659 * Write SPI Tx Fifo Control Word-2. 5660 */ 5661 wr_data = ((MSGTYPE_HWR * 0x0100) | WREN_OPCODE); 5662 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5663 5664 /* 5665 * Write SPI Tx Fifo Control Word-3. 5666 */ 5667 wr_data = ((WRSR_OPCODE * 0x100) | (0x2)); 5668 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5669 5670 /* 5671 * Write SPI Tx Fifo Control Word-4. 5672 */ 5673 wrsr_data = enable ? 0x2 : 0xc; 5674 wr_data = ((wrsr_data * 0x0100) | wrsr_data); 5675 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5676 5677 /* 5678 * Write SPI Control Register Write Command. 5679 */ 5680 count = 2; 5681 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 5682 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5683 5684 /* 5685 * Write SPI Control -1 Register Address. 5686 */ 5687 wr_data = SPI_CTRL_1_L; 5688 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5689 5690 /* 5691 * Write SPI Control -1 Register Word-1. 5692 */ 5693 wr_data = 0x0101; 5694 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5695 5696 /* 5697 * Write SPI Control -1 Register Word-2. 5698 */ 5699 wr_data = 0x0003; 5700 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 5701 5702 /* 5703 * Wait For WRSR Command To be written. 5704 */ 5705 SOC_IF_ERROR_RETURN(phy_84740_rom_wait(unit, port)); 5706 5707 return SOC_E_NONE; 5708 } 5709 5710 STATIC int _phy84740_init_ucode_bcst(int unit, int port, int cmd) 5711 { 5712 uint16 data16; 5713 uint16 mask16; 5714 uint16 phy_id; 5715 int j; 5716 uint16 num_words; 5717 int i; 5718 uint16 chip_mode; 5719 int num_lanes; 5720 uint8 *fw_ptr; 5721 int fw_length; 5722 phy_ctrl_t *pc; 5723 5724 pc = EXT_PHY_SW_STATE(unit, port); 5725 num_lanes = PHY84740_SINGLE_PORT_MODE(pc) ? 4 : 1; 5726 5727 #ifdef BCM_WARM_BOOT_SUPPORT 5728 if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)){ 5729 return SOC_E_NONE; 5730 } 5731 #endif 5732 5733 if (cmd == PHYCTRL_UCODE_BCST_SETUP) { 5734 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 5735 (unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 5736 &chip_mode)); 5737 5738 LOG_INFO(BSL_LS_SOC_PHY, 5739 (BSL_META_U(unit, 5740 "PHY84740 BCST start: u=%d p=%d\n"), unit, port)); 5741 /* check the current chip mode, switch to quad if in single port mode */ 5742 if ((chip_mode & PHY84740_PMAD_CHIP_MODE_MASK) == 5743 PHY84740_PMAD_MODE_40G) { 5744 LOG_INFO(BSL_LS_SOC_PHY, 5745 (BSL_META_U(unit, 5746 "PHY84740 BCST mode switch: u=%d p=%d\n"), 5747 unit, port)); 5748 SOC_IF_ERROR_RETURN(_phy_84740_single_to_quad_mode 5749 (unit, port, NULL)); 5750 } 5751 5752 /* program the bcst register. do 4 lanes for single port configuration */ 5753 phy_id = pc->phy_id; 5754 /* configure all four ports */ 5755 for (i = 0; i < num_lanes; i++) { 5756 if (num_lanes > 1) { 5757 pc->phy_id = (phy_id & (~0x3)) + i; /* Port 3, 2, 1 and 0 */ 5758 } 5759 SOC_IF_ERROR_RETURN 5760 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc8fe, 0xffff)); 5761 } 5762 /* restore the original phy_id */ 5763 pc->phy_id = phy_id; 5764 return SOC_E_NONE; 5765 } else if (cmd == PHYCTRL_UCODE_BCST_uC_SETUP) { 5766 LOG_INFO(BSL_LS_SOC_PHY, 5767 (BSL_META_U(unit, 5768 "PHY84740 BCST1: u=%d p=%d\n"), unit, port)); 5769 /* clear SPA ctrl reg bit 15 and bit 13. 5770 * bit 15, 0-use MDIO download to SRAM, 1 SPI-ROM download to SRAM 5771 * bit 13, 0 clear download done status, 1 skip download 5772 */ 5773 mask16 = (1 << 13) | (1 << 15); 5774 data16 = 0; 5775 SOC_IF_ERROR_RETURN 5776 (MODIFY_PHY84740_MMF_PMA_PMD_REG 5777 (unit, pc, PHY84740_PMAD_SPA_CTRL_REG, data16, mask16)); 5778 5779 /* set SPA ctrl reg bit 14, 1 RAM boot, 0 internal ROM boot */ 5780 mask16 = 1 << 14; 5781 data16 = mask16; 5782 SOC_IF_ERROR_RETURN 5783 (MODIFY_PHY84740_MMF_PMA_PMD_REG 5784 (unit, pc, PHY84740_PMAD_SPA_CTRL_REG, data16, mask16)); 5785 5786 /* misc_ctrl1 reg bit 3 to 1 for 32k downloading size */ 5787 mask16 = 1 << 3; 5788 data16 = mask16; 5789 SOC_IF_ERROR_RETURN 5790 (MODIFY_PHY84740_MMF_PMA_PMD_REG 5791 (unit, pc, PHY84740_PMAD_MISC_CTRL1_REG, data16, mask16)); 5792 5793 /* apply bcst Reset to start download code from MDIO */ 5794 SOC_IF_ERROR_RETURN(WRITE_PHY84740_PMA_PMD_CTRLr(unit, pc, 0x8000)); 5795 return SOC_E_NONE; 5796 } else if (cmd == PHYCTRL_UCODE_BCST_ENABLE) { 5797 LOG_INFO(BSL_LS_SOC_PHY, 5798 (BSL_META_U(unit, 5799 "PHY84740 BCST2: u=%d p=%d\n"), unit, port)); 5800 5801 /* reset clears bcst register */ 5802 /* restore bcst register after reset */ 5803 phy_id = pc->phy_id; 5804 /* configure all four ports */ 5805 for (i = 0; i < num_lanes; i++) { 5806 if (num_lanes > 1) { 5807 pc->phy_id = (phy_id & (~0x3)) + i; /* Port 3, 2, 1 and 0 */ 5808 } 5809 SOC_IF_ERROR_RETURN 5810 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc8fe, 0xffff)); 5811 } 5812 /* restore the original phy_id */ 5813 pc->phy_id = phy_id; 5814 return SOC_E_NONE; 5815 } else if (cmd == PHYCTRL_UCODE_BCST_LOAD) { 5816 LOG_INFO(BSL_LS_SOC_PHY, 5817 (BSL_META_U(unit, 5818 "firmware_bcst,device name %s: u=%d p=%d\n"), 5819 pc->dev_name ? pc->dev_name : "NULL", unit, port)); 5820 /* find the right firmware */ 5821 if (pc->dev_name == dev_name_84740) { 5822 fw_ptr = phy84740_ucode_bin; 5823 fw_length = phy84740_ucode_bin_len; 5824 } else if (pc->dev_name == dev_name_84752) { 5825 fw_ptr = phy84752_ucode_bin; 5826 fw_length = phy84752_ucode_bin_len; 5827 } else if (pc->dev_name == dev_name_84753) { 5828 fw_ptr = phy84753_ucode_bin; 5829 fw_length = phy84753_ucode_bin_len; 5830 } else if (pc->dev_name == dev_name_84754) { 5831 fw_ptr = phy84754_ucode_bin; 5832 fw_length = phy84754_ucode_bin_len; 5833 } else if (pc->dev_name == dev_name_84064) { 5834 fw_ptr = phy84064_ucode_bin; 5835 fw_length = phy84064_ucode_bin_len; 5836 } else if (pc->dev_name == dev_name_84784) { 5837 fw_ptr = phy84784_ucode_bin; 5838 fw_length = phy84784_ucode_bin_len; 5839 } else { 5840 /* invalid device name */ 5841 LOG_WARN(BSL_LS_SOC_PHY, 5842 (BSL_META_U(unit, 5843 "firmware_bcst,invalid device name %s: u=%d p=%d\n"), 5844 pc->dev_name ? pc->dev_name : "NULL", unit, port)); 5845 return SOC_E_NONE; 5846 } 5847 5848 /* wait for 2ms for M8051 start and 5ms to initialize the RAM */ 5849 sal_usleep(10000); /* Wait for 10ms */ 5850 5851 /* Write Starting Address, where the Code will reside in SRAM */ 5852 data16 = 0x8000; 5853 SOC_IF_ERROR_RETURN 5854 (WRITE_PHY84740_MMF_PMA_PMD_REG 5855 (unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, data16)); 5856 5857 /* make sure address word is read by the micro */ 5858 sal_udelay(10); /* Wait for 10us */ 5859 5860 /* Write SPI SRAM Count Size */ 5861 data16 = (fw_length) / 2; 5862 SOC_IF_ERROR_RETURN 5863 (WRITE_PHY84740_MMF_PMA_PMD_REG 5864 (unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, data16)); 5865 5866 /* make sure read by the micro */ 5867 sal_udelay(10); /* Wait for 10us */ 5868 5869 /* Fill in the SRAM */ 5870 num_words = (fw_length - 1); 5871 for (j = 0; j < num_words; j += 2) { 5872 /* Make sure the word is read by the Micro */ 5873 sal_udelay(10); 5874 5875 data16 = (fw_ptr[j] << 8) | fw_ptr[j + 1]; 5876 5877 SOC_IF_ERROR_RETURN 5878 (WRITE_PHY84740_MMF_PMA_PMD_REG 5879 (unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, data16)); 5880 } 5881 return SOC_E_NONE; 5882 } else if (cmd == PHYCTRL_UCODE_BCST_END) { 5883 LOG_INFO(BSL_LS_SOC_PHY, 5884 (BSL_META_U(unit, 5885 "PHY84740 BCST end: u=%d p=%d\n"), unit, port)); 5886 5887 /* make sure last code word is read by the micro */ 5888 sal_udelay(20); 5889 5890 /* first disable bcst mode */ 5891 phy_id = pc->phy_id; 5892 for (i = 0; i < num_lanes; i++) { 5893 if (num_lanes > 1) { 5894 pc->phy_id = (phy_id & (~0x3)) + i; /* Port 3, 2, 1 and 0 */ 5895 } 5896 SOC_IF_ERROR_RETURN 5897 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc8fe, 0x0)); 5898 5899 /* Read Hand-Shake message (Done) from Micro */ 5900 SOC_IF_ERROR_RETURN 5901 (READ_PHY84740_MMF_PMA_PMD_REG 5902 (unit, pc, PHY84740_PMAD_M8051_MSGOUT_REG, &data16)); 5903 5904 /* Download done message */ 5905 LOG_INFO(BSL_LS_SOC_PHY, 5906 (BSL_META_U(unit, 5907 "u=%d p=%d MDIO firmware download done message: 0x%x\n"), 5908 unit, port, data16)); 5909 5910 /* Clear LASI status */ 5911 SOC_IF_ERROR_RETURN 5912 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16)); 5913 } 5914 /* restore the original phy_id */ 5915 pc->phy_id = phy_id; 5916 5917 /* Wait for LASI to be asserted when M8051 writes checksum to MSG_OUTr */ 5918 sal_udelay(100); /* Wait for 100 usecs */ 5919 5920 phy_id = pc->phy_id; 5921 for (i = 0; i < num_lanes; i++) { 5922 if (num_lanes > 1) { 5923 pc->phy_id = (phy_id & (~0x3)) + i; /* Port 3, 2, 1 and 0 */ 5924 } 5925 SOC_IF_ERROR_RETURN 5926 (READ_PHY84740_MMF_PMA_PMD_REG 5927 (unit, pc, PHY84740_PMAD_M8051_MSGOUT_REG, &data16)); 5928 5929 /* Need to check if checksum is correct */ 5930 SOC_IF_ERROR_RETURN 5931 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &data16)); 5932 5933 if (data16 != 0x600D) { 5934 /* Bad CHECKSUM */ 5935 LOG_CLI((BSL_META_U(unit, 5936 "firmware_bcst downlad failure: port %d " 5937 "Incorrect Checksum %x\n"), port, data16)); 5938 return SOC_E_FAIL; 5939 } 5940 5941 /* read Rev-ID */ 5942 SOC_IF_ERROR_RETURN 5943 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1A, &data16)); 5944 LOG_INFO(BSL_LS_SOC_PHY, 5945 (BSL_META_U(unit, 5946 "u=%d p=%d MDIO Firmware download revID: 0x%x\n"), 5947 unit, port, data16)); 5948 } 5949 /* restore the original phy_id */ 5950 pc->phy_id = phy_id; 5951 5952 return SOC_E_NONE; 5953 } else { 5954 LOG_WARN(BSL_LS_SOC_PHY, 5955 (BSL_META_U(unit, 5956 "u=%d p=%d firmware_bcst: invalid cmd 0x%x\n"), 5957 unit, port, cmd)); 5958 } 5959 5960 return SOC_E_FAIL; 5961 } 5962 5963 /* 5964 * Function: 5965 * phy_84740_firmware_set 5966 * Purpose: 5967 * program the given firmware into the SPI-ROM 5968 * Parameters: 5969 * unit - StrataSwitch unit #. 5970 * port - StrataSwitch port #. 5971 * offset - offset to the data stream 5972 * array - the given data 5973 * datalen- the data length 5974 * Returns: 5975 * SOC_E_NONE 5976 */ 5977 5978 STATIC int 5979 phy_84740_firmware_set(int unit, int port, int offset, uint8 *array, 5980 int datalen) 5981 { 5982 uint16 saved_phy_addr; 5983 int ix; 5984 phy_ctrl_t *pc; 5985 uint32 devid; 5986 uint32 uCode_devid; 5987 5988 /* overload this function a littl bit if array == NULL 5989 * special handling for init. uCode broadcast. Internal use only 5990 */ 5991 if (array == NULL) { 5992 return _phy84740_init_ucode_bcst(unit, port, offset); 5993 } 5994 5995 pc = EXT_PHY_SW_STATE(unit, port); 5996 5997 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 5998 (pc->unit, pc->port, pc, &devid)); 5999 6000 /* first validate the firmware is for the configured device 6001 * 84740 has 1.5V from TXDRV pin, 84754 is internally wired at 1.0V. 6002 * If the 84754 firmware which programs chip for 1.0V is loaded 6003 * to the 84740, then it may damage the device and module. 6004 * 6005 * Chip ID is at addresses 0x7FF9, 0x7FFA, 0x7FFB.e.g. 6006 * for 84740, [0x7FF9] = 0x08, [0x7FFA] = 0x47, [0x7FFB] = 0x40. 6007 * Version number is at 0x7FFC-0x7FFD 6008 */ 6009 6010 /* length should be at least 0xFFFE */ 6011 if (datalen < PHY84740_UCODE_DEVID_ADDR+3) { 6012 LOG_WARN(BSL_LS_SOC_PHY, 6013 (BSL_META_U(unit, 6014 "firmware_set, wrong firmware len=0x%x : u=%d p=%d\n"), 6015 datalen, unit, port)); 6016 return SOC_E_PARAM; 6017 } 6018 6019 /* check the firmware devid matches the configured devid */ 6020 ix = PHY84740_UCODE_DEVID_ADDR; 6021 uCode_devid = (array[ix] << 16) | (array[ix + 1] << 8) | array[ix + 2]; 6022 6023 if (uCode_devid != devid) { 6024 LOG_WARN(BSL_LS_SOC_PHY, 6025 (BSL_META_U(unit, 6026 "firmware_set,u=%d p=%d: Firmware device " 6027 "type(0x%x) does not match configured device type(0x%x)\n"), 6028 unit, port,uCode_devid,devid)); 6029 return SOC_E_PARAM; 6030 } 6031 6032 if (PHY84740_SINGLE_PORT_MODE(pc)) { 6033 /* switch to quad-mode */ 6034 SOC_IF_ERROR_RETURN(_phy_84740_single_to_quad_mode(unit, port, NULL)); 6035 } 6036 saved_phy_addr = pc->phy_id; 6037 6038 LOG_INFO(BSL_LS_SOC_PHY, 6039 (BSL_META_U(unit, 6040 "firmware_set init,quad port : u=%d p=%d\n"), 6041 unit, port)); 6042 /* configure all four lanes to bcst mode */ 6043 for (ix = 0; ix < 4; ix++) { 6044 pc->phy_id = (saved_phy_addr & (~0x3)) + ix; 6045 SOC_IF_ERROR_RETURN 6046 (WRITE_PHY84740_MMF_PMA_PMD_REG 6047 (unit, pc, PHY84740_PMAD_BCST_REG, 0xffff)); 6048 } 6049 pc->phy_id = saved_phy_addr; 6050 6051 /* place all uC in reset */ 6052 SOC_IF_ERROR_RETURN 6053 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA10, 0x018f)); 6054 6055 /* disable all port's SPI */ 6056 SOC_IF_ERROR_RETURN 6057 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC843, 0x000f)); 6058 6059 SOC_IF_ERROR_RETURN 6060 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC840, 0x000c)); 6061 6062 /* Set bit 0 (spa enable) in C848 for master channel ? */ 6063 SOC_IF_ERROR_RETURN 6064 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC848, 0x2000, 0x2000)); 6065 6066 /* disable the bcst mode for all channels */ 6067 SOC_IF_ERROR_RETURN 6068 (WRITE_PHY84740_MMF_PMA_PMD_REG 6069 (unit, pc, PHY84740_PMAD_BCST_REG, 0xfffe)); 6070 6071 SOC_IF_ERROR_RETURN 6072 (_phy_84740_firmware_to_rom(unit, port, offset, array, datalen)); 6073 6074 /* switch back to single mode */ 6075 if (PHY84740_SINGLE_PORT_MODE(pc)) { 6076 /* switch to quad-mode */ 6077 SOC_IF_ERROR_RETURN(_phy_84740_quad_to_single_mode(unit, port)); 6078 } 6079 return SOC_E_NONE; 6080 } 6081 6082 STATIC int 6083 _phy_84740_firmware_to_rom(int unit, int port, int offset, uint8 *array, 6084 int datalen) 6085 { 6086 uint16 rd_data; 6087 uint16 wr_data; 6088 int j; 6089 int i = 0; 6090 int count; 6091 uint8 spi_values[WR_BLOCK_SIZE]; 6092 uint16 data16; 6093 soc_timeout_t to; 6094 phy_ctrl_t *pc; 6095 6096 pc = EXT_PHY_SW_STATE(unit, port); 6097 6098 /* 6099 * Enable SPI for Port0 6100 */ 6101 SOC_IF_ERROR_RETURN 6102 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC843, 0x0000)); 6103 SOC_IF_ERROR_RETURN 6104 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC840, 0x0000)); 6105 /* 6106 * Remove M8051 resets for port 0. 6107 * and wait for Micro to complete Init. 6108 */ 6109 /* clear bits 3:0 */ 6110 SOC_IF_ERROR_RETURN 6111 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA10, 0, 0xf)); 6112 sal_usleep(10000); 6113 6114 /* set bit(request) in 0xc848 for the required channel, remove done bit */ 6115 SOC_IF_ERROR_RETURN 6116 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC848, 0, 0x2000)); 6117 6118 /* enable SPI port enable */ 6119 SOC_IF_ERROR_RETURN 6120 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC848, 0xc004, 0xc004)); 6121 6122 /* 6123 * Read LASI Status registers To clear initial Failure status. 6124 */ 6125 SOC_IF_ERROR_RETURN 6126 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &rd_data)); 6127 SOC_IF_ERROR_RETURN 6128 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9004, &rd_data)); 6129 SOC_IF_ERROR_RETURN 6130 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9005, &rd_data)); 6131 6132 /* 6133 * Enable the LASI For Message out. 6134 */ 6135 SOC_IF_ERROR_RETURN 6136 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9000, 0x0004)); 6137 /* 6138 * 0x9002, bit 2 Is Rx Alarm enabled For LASI. 6139 */ 6140 SOC_IF_ERROR_RETURN 6141 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9002, 0x0004)); 6142 /* 6143 * Read Any Residual Message out register. 6144 */ 6145 SOC_IF_ERROR_RETURN 6146 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &rd_data)); 6147 /* 6148 * Clear LASI Message Out Status. 6149 */ 6150 SOC_IF_ERROR_RETURN 6151 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &rd_data)); 6152 6153 /* set SPI-ROM write enable */ 6154 SOC_IF_ERROR_RETURN(phy_84740_rom_write_enable_set(unit, port, 1)); 6155 6156 LOG_INFO(BSL_LS_SOC_PHY, 6157 (BSL_META_U(unit, 6158 "init0: u=%d p=%d\n"), 6159 unit, port)); 6160 6161 for (j = 0; j < datalen; j += WR_BLOCK_SIZE) { 6162 /* 6163 * Setup SPI Controller. 6164 */ 6165 count = 2; 6166 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 6167 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6168 6169 /* Write SPI Control -2 Register Address. */ 6170 wr_data = SPI_CTRL_2_L; 6171 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6172 6173 /* Write SPI Control -2 Register Word-1. */ 6174 wr_data = 0x8200; 6175 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6176 6177 /* Write SPI Control -2 Register Word-2. */ 6178 wr_data = 0x0100; 6179 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6180 6181 /* Fill-up SPI Transmit Fifo. 6182 * Write SPI Control Register Write Command. 6183 */ 6184 count = 4 + (WR_BLOCK_SIZE / 2); 6185 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 6186 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6187 6188 /* Write Tx Fifo Register Address. */ 6189 wr_data = SPI_TXFIFO; 6190 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6191 6192 /* Write SPI Tx Fifo Control Word-1. */ 6193 wr_data = ((1 * 0x0100) | MSGTYPE_HWR); 6194 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6195 6196 /* Write SPI Tx Fifo Control Word-2. */ 6197 wr_data = ((MSGTYPE_HWR * 0x0100) | WREN_OPCODE); 6198 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6199 6200 /* Write SPI Tx Fifo Control Word-3. */ 6201 wr_data = ((WR_OPCODE * 0x0100) | (0x3 + WR_BLOCK_SIZE)); 6202 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6203 6204 /* Write SPI Tx Fifo Control Word-4. */ 6205 wr_data = (((j & 0x00FF) * 0x0100) | ((j & 0xFF00) / 0x0100)); 6206 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6207 6208 LOG_INFO(BSL_LS_SOC_PHY, 6209 (BSL_META_U(unit, 6210 "loop: u=%d p=%d,inxj: %d,inxi:%d\n"), 6211 unit, port,j,i)); 6212 6213 if (datalen < (j + WR_BLOCK_SIZE)) { /* last block */ 6214 sal_memset(spi_values, 0, WR_BLOCK_SIZE); 6215 sal_memcpy(spi_values, &array[j], datalen - j); 6216 6217 for (i = 0; i < WR_BLOCK_SIZE; i += 2) { 6218 /* Write SPI Tx Fifo Data Word-4. */ 6219 wr_data = ((spi_values[i + 1] * 0x0100) | spi_values[i]); 6220 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6221 } 6222 } else { 6223 for (i = 0; i < WR_BLOCK_SIZE; i += 2) { 6224 /* Write SPI Tx Fifo Data Word-4. */ 6225 wr_data = ((array[j + i + 1] * 0x0100) | array[j + i]); 6226 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6227 } 6228 } 6229 6230 /* 6231 * Set-up SPI Controller To Transmit. 6232 * Write SPI Control Register Write Command. 6233 */ 6234 count = 2; 6235 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 6236 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6237 6238 wr_data = SPI_CTRL_1_L; 6239 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6240 6241 /* Write SPI Control -1 Register Word-1. */ 6242 wr_data = 0x0501; 6243 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6244 6245 /* Write SPI Control -1 Register Word-2. */ 6246 wr_data = 0x0003; 6247 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6248 6249 /* Wait For 64 bytes To be written. */ 6250 SOC_IF_ERROR_RETURN(phy_84740_rom_wait(unit, port)); 6251 6252 } /* SPI_WRITE */ 6253 6254 /* clear SPI-ROM write enable */ 6255 SOC_IF_ERROR_RETURN(phy_84740_rom_write_enable_set(unit, port, 0)); 6256 6257 /* Disable SPI EEPROM. */ 6258 count = 2; 6259 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 6260 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6261 6262 /* Write SPI Control -2 Register Address. */ 6263 wr_data = SPI_CTRL_2_L; 6264 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6265 6266 /* Write SPI Control -2 Register Word-1. */ 6267 wr_data = 0x8200; 6268 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6269 6270 /* Write SPI Control -2 Register Word-2. */ 6271 wr_data = 0x0100; 6272 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6273 6274 /* Fill-up SPI Transmit Fifo With SPI EEPROM Messages. */ 6275 count = 2; 6276 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 6277 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6278 6279 /* Write Tx Fifo Register Address. */ 6280 wr_data = SPI_TXFIFO; 6281 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6282 6283 /* Write SPI Tx Fifo Control Word-1. */ 6284 wr_data = ((0x1 * 0x0100) | MSGTYPE_HWR); 6285 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6286 6287 /* Write SPI Tx Fifo Control Word-2. */ 6288 wr_data = WRDI_OPCODE; 6289 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6290 6291 /* Write SPI Control Register Write Command. */ 6292 count = 2; 6293 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 6294 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6295 6296 /* Write SPI Control -1 Register Address. */ 6297 wr_data = SPI_CTRL_1_L; 6298 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6299 6300 /* Write SPI Control -1 Register Word-1. */ 6301 wr_data = 0x0101; 6302 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6303 6304 /* Write SPI Control -1 Register Word-2. */ 6305 wr_data = 0x0003; 6306 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6307 6308 /* Wait For WRDI Command To be written */ 6309 rd_data = 0; 6310 soc_timeout_init(&to, WR_TIMEOUT, 0); 6311 do { 6312 /* Write SPI Control Register Read Command. */ 6313 count = 1; 6314 wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count); 6315 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6316 wr_data = SPI_CTRL_1_L; 6317 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 6318 6319 /* extra reads to clear the status */ 6320 SOC_IF_ERROR_RETURN 6321 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16)); 6322 SOC_IF_ERROR_RETURN 6323 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16)); 6324 6325 if (rd_data & 0x0100) { 6326 break; 6327 } 6328 } while (!soc_timeout_check(&to)); 6329 6330 if (!(rd_data & 0x0100)) { 6331 LOG_ERROR(BSL_LS_SOC_PHY, 6332 (BSL_META_U(unit, 6333 "phy_84740_rom_program: u = %d p = %d " 6334 "WRDI command timeout\n"), unit, port)); 6335 return SOC_E_TIMEOUT; 6336 } 6337 6338 LOG_INFO(BSL_LS_SOC_PHY, 6339 (BSL_META_U(unit, 6340 "phy_84740_rom_program: u=%d p=%d done\n"), unit, port)); 6341 6342 return SOC_E_NONE; 6343 } 6344 6345 static int 6346 write_message(int unit, phy_ctrl_t *pc, uint16 wrdata, uint16 *rddata) 6347 { 6348 6349 uint16 tmp_data = 0; 6350 soc_timeout_t to; 6351 6352 SOC_IF_ERROR_RETURN 6353 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA12, wrdata)); 6354 6355 soc_timeout_init(&to, WR_TIMEOUT, 0); 6356 do { 6357 SOC_IF_ERROR_RETURN 6358 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9005, &tmp_data)); 6359 if (tmp_data & 0x4) 6360 break; 6361 } while (!soc_timeout_check(&to)); 6362 if (!(tmp_data & 0x4)) { 6363 LOG_ERROR(BSL_LS_SOC_PHY, 6364 (BSL_META_U(unit, 6365 "write_message failed: wrdata %04x\n"), wrdata)); 6366 return SOC_E_FAIL; 6367 } 6368 6369 SOC_IF_ERROR_RETURN 6370 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &tmp_data)); 6371 *rddata = tmp_data; 6372 SOC_IF_ERROR_RETURN 6373 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &tmp_data)); 6374 6375 return SOC_E_NONE; 6376 } 6377 6378 /* 6379 * Function: 6380 * phy_84740_precondition_before_probe 6381 * Purpose: 6382 * When the device is in 40G, ie. after a power reset, and the 10G 6383 * port being probed does not have the 40G address in PRTAD, the 6384 * device will not respond until the port that has the 40G address 6385 * is probed. To avoid not programming ports correctly, make 6386 * sure the device is in quad (4x10G) PMD mode when the SDK port is 10G. 6387 * Parameters: 6388 * unit - StrataSwitch unit #. 6389 * pc - phy ctrl descriptor. 6390 * Returns: 6391 * SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error> 6392 */ 6393 6394 STATIC int 6395 phy_84740_precondition_before_probe(int unit, phy_ctrl_t *pc) 6396 { 6397 int ids; 6398 int rv = SOC_E_NOT_FOUND; 6399 uint16 saved_phy_id; 6400 uint16 id0, id1; 6401 uint32 devid; 6402 6403 /* Not required when the port is single PMD */ 6404 if (PHY84740_SINGLE_PORT_MODE(pc)) { 6405 LOG_INFO(BSL_LS_SOC_PHY, 6406 (BSL_META_U(unit, 6407 "PMD must not be called when in single PMD\n"))); 6408 return rv; 6409 } 6410 6411 saved_phy_id = pc->phy_id; 6412 6413 /* Look for first address that responds */ 6414 for (ids = 0; ids < 4; ids++) { 6415 6416 pc->phy_id = (saved_phy_id & ~0x3) + ids; 6417 LOG_INFO(BSL_LS_SOC_PHY, 6418 (BSL_META_U(unit, 6419 "Try device with address %x\n"), pc->phy_id)); 6420 6421 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 6422 (pc->unit, pc->port, pc, &devid)); 6423 6424 6425 /* 6426 * Make sure the device has the correct dev IDs 6427 * Note that this is being called either because the soc probe found 6428 * the ids or there was an id override. In the later case, the device 6429 * might not have the 84740 ids so this PMD setup will not be supported 6430 */ 6431 id0 = 0; 6432 READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 6433 2 /*PHY84740_DEV1_PMD_IDENTIFIER_REGISTER_0 */, 6434 &id0); 6435 if (id0 == 0xffff) { 6436 continue; 6437 } 6438 id1 = 0; 6439 READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 6440 3 /*PHY84740_DEV1_PMD_IDENTIFIER_REGISTER_1 */, 6441 &id1); 6442 if (id1 == 0xffff) { 6443 continue; 6444 } 6445 6446 switch(devid) { 6447 case PHY84740_ID_84740: 6448 case PHY84740_ID_84752: 6449 case PHY84740_ID_84753: 6450 case PHY84740_ID_84754: 6451 case PHY84740_ID_84064: 6452 break; 6453 default: 6454 if (PHY84740_IS_QUADRA(devid)) { 6455 break; 6456 } else { /* not found */ 6457 LOG_WARN(BSL_LS_SOC_PHY, 6458 (BSL_META_U(unit, 6459 "port %d: BCM84xxx type PHY device detected, please use " 6460 "phy_84<xxx> config variable to select the specific type\n"), 6461 pc->port)); 6462 continue; 6463 } 6464 } 6465 6466 /* switch to quad-mode */ 6467 SOC_IF_ERROR_RETURN(_phy_84740_single_to_quad_mode(unit, pc->port, pc)); 6468 6469 /* Found the address that responds and the device now is in 4x10G */ 6470 rv = SOC_E_NONE; 6471 break; 6472 } 6473 6474 pc->phy_id = saved_phy_id; 6475 6476 return rv; 6477 } 6478 6479 6480 /* 6481 * Function: 6482 * phy_84740_probe 6483 * Purpose: 6484 * Complement the generic phy probe routine to identify this phy when its 6485 * phy id0 and id1 is same as some other phy's. 6486 * Parameters: 6487 * unit - StrataSwitch unit #. 6488 * pc - phy ctrl descriptor. 6489 * Returns: 6490 * SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error> 6491 */ 6492 STATIC int phy_84740_probe(int unit, phy_ctrl_t *pc) 6493 { 6494 uint32 devid; 6495 6496 SOC_IF_ERROR_RETURN(_phy_84740_config_devid 6497 (pc->unit, pc->port, pc, &devid)); 6498 6499 if (devid == PHY84740_ID_84740) { 6500 pc->dev_name = dev_name_84740; 6501 } else if (devid == PHY84740_ID_84752) { 6502 pc->dev_name = dev_name_84752; 6503 } else if (devid == PHY84740_ID_84753) { 6504 pc->dev_name = dev_name_84753; 6505 } else if (devid == PHY84740_ID_84754) { 6506 pc->dev_name = dev_name_84754; 6507 } else if (devid == PHY84740_ID_84064) { 6508 pc->dev_name = dev_name_84064; 6509 } else if (PHY84740_IS_QUADRA(devid)) { 6510 /*pc->dev_name = already set;*/ 6511 } else { /* not found */ 6512 LOG_WARN(BSL_LS_SOC_PHY, 6513 (BSL_META_U(unit, 6514 "port %d: BCM84xxx type PHY device detected, please use " 6515 "phy_84<xxx> config variable to select the specific type\n"), 6516 pc->port)); 6517 return SOC_E_NOT_FOUND; 6518 } 6519 pc->size = sizeof(PHY84740_DEV_DESC_t); 6520 return SOC_E_NONE; 6521 } 6522 6523 STATIC int 6524 _phy_84740_bsc_rw(int unit, soc_port_t port, int dev_addr, int opr, 6525 int addr, int count, void *data_array, uint32 ram_start) 6526 { 6527 phy_ctrl_t *pc; 6528 soc_timeout_t to; 6529 uint16 data16; 6530 int i; 6531 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT) 6532 sal_usecs_t start; 6533 sal_usecs_t end; 6534 #endif /* defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT */ 6535 int access_type; 6536 int data_type; 6537 6538 LOG_INFO(BSL_LS_SOC_PHY, 6539 (BSL_META_U(unit, 6540 "phy_84740_bsc_read: u=%d p=%d addr=%04x\n"), 6541 unit, port, addr)); 6542 6543 if (!data_array) { 6544 return SOC_E_PARAM; 6545 } 6546 6547 if (count > PHY84740_BSC_XFER_MAX) { 6548 return SOC_E_PARAM; 6549 } 6550 6551 pc = EXT_PHY_SW_STATE(unit, port); 6552 data_type = PHY84740_I2C_DATA_TYPE(opr); 6553 access_type = PHY84740_I2C_ACCESS_TYPE(opr); 6554 6555 if (access_type == PHY84740_I2CDEV_WRITE) { 6556 for (i = 0; i < count; i++) { 6557 if (data_type == PHY84740_I2C_8BIT) { 6558 SOC_IF_ERROR_RETURN 6559 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, ram_start + i, 6560 ((uint8 *) data_array)[i])); 6561 } else { /* 16 bit */ 6562 SOC_IF_ERROR_RETURN 6563 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, ram_start + i, 6564 ((uint16 *) 6565 data_array)[i])); 6566 } 6567 } 6568 } 6569 6570 data16 = ram_start; 6571 SOC_IF_ERROR_RETURN 6572 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8004, data16)); 6573 SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8003, addr)); 6574 SOC_IF_ERROR_RETURN 6575 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8002, count)); 6576 6577 data16 = 1; 6578 data16 |= (dev_addr << 9); 6579 if (access_type == PHY84740_I2CDEV_WRITE) { 6580 data16 |= PHY84740_WR_FREQ_400KHZ; 6581 } 6582 6583 SOC_IF_ERROR_RETURN 6584 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8005, data16)); 6585 6586 if (access_type == PHY84740_I2CDEV_WRITE) { 6587 data16 = 0x8000 | PHY84740_BSC_WRITE_OP; 6588 } else { 6589 data16 = 0x8000 | PHY84740_BSC_READ_OP; 6590 } 6591 6592 if (data_type == PHY84740_I2C_16BIT) { 6593 data16 |= (1 << 12); 6594 } 6595 6596 /* for single port mode, there should be only one I2C interface active 6597 * from lane0. The 0x800x register block is bcst type registers. If writing 6598 * to 0x8000 directly, it will enable all four I2C masters. Use indirect access 6599 * to enable only the lane 0. 6600 */ 6601 6602 if (PHY84740_SINGLE_PORT_MODE(pc)) { 6603 6604 /* point to lane 0 */ 6605 SOC_IF_ERROR_RETURN 6606 (WRITE_PHY84740_MMF_PMA_PMD_REG 6607 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 6608 6609 /* indirect access: 0x8000=data16 */ 6610 SOC_IF_ERROR_RETURN 6611 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd0c, 0x8000)); 6612 SOC_IF_ERROR_RETURN 6613 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd0d, data16)); 6614 6615 /* issue the indirect access command */ 6616 SOC_IF_ERROR_RETURN 6617 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd13, 0x3)); 6618 6619 soc_timeout_init(&to, 1000000, 0); 6620 while (!soc_timeout_check(&to)) { 6621 SOC_IF_ERROR_RETURN 6622 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd13, &data16)); 6623 if (!data16) { 6624 break; 6625 } 6626 } 6627 if (data16) { 6628 LOG_WARN(BSL_LS_SOC_PHY, 6629 (BSL_META_U(unit, 6630 "port %d: Fail register 0xcd13 status 0x%x\n"), 6631 port,data16)); 6632 return SOC_E_TIMEOUT; 6633 } 6634 } else { 6635 SOC_IF_ERROR_RETURN 6636 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8000, data16)); 6637 } 6638 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT) 6639 start = sal_time_usecs(); 6640 #endif /* defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT */ 6641 soc_timeout_init(&to, 1000000, 0); 6642 while (!soc_timeout_check(&to)) { 6643 SOC_IF_ERROR_RETURN 6644 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8000, &data16)); 6645 if (((data16 & PHY84740_2W_STAT) == PHY84740_2W_STAT_COMPLETE)) { 6646 break; 6647 } 6648 } 6649 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT) 6650 end = sal_time_usecs(); 6651 #endif /* defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT */ 6652 /* need some delays */ 6653 sal_usleep(10000); 6654 6655 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT) 6656 LOG_INFO(BSL_LS_SOC_PHY, 6657 (BSL_META_U(unit, 6658 "BSC command status %d time=%d\n"), 6659 (data16 & PHY84740_2W_STAT), SAL_USECS_SUB(end, start))); 6660 #endif /* defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT */ 6661 6662 if (access_type == PHY84740_I2CDEV_WRITE) { 6663 return SOC_E_NONE; 6664 } 6665 6666 if ((data16 & PHY84740_2W_STAT) == PHY84740_2W_STAT_COMPLETE) { 6667 for (i = 0; i < count; i++) { 6668 SOC_IF_ERROR_RETURN 6669 (READ_PHY84740_MMF_PMA_PMD_REG 6670 (unit, pc, (ram_start + i), &data16)); 6671 if (data_type == PHY84740_I2C_16BIT) { 6672 ((uint16 *)data_array)[i] = data16; 6673 LOG_INFO(BSL_LS_SOC_PHY, 6674 (BSL_META_U(unit, 6675 "%04x "), data16)); 6676 } else { 6677 ((uint8 *)data_array)[i] = (uint8)data16; 6678 LOG_INFO(BSL_LS_SOC_PHY, 6679 (BSL_META_U(unit, 6680 "%02x "), data16)); 6681 } 6682 } 6683 } 6684 return SOC_E_NONE; 6685 } 6686 6687 /* 6688 * Read a slave device such as NVRAM/EEPROM connected to the 84740's I2C 6689 * interface. This function will be mainly used for diagnostic or workaround 6690 * purpose. 6691 * Note: 6692 * The size of read_array buffer must be greater than or equal to the 6693 * parameter nbytes. 6694 * usage example: 6695 * Retrieve the first 100 byte data of the non-volatile storage device with 6696 * I2C bus device address 0x50(default SPF eeprom I2C address) on unit 0, 6697 * port 2. 6698 * uint8 data8[100]; 6699 * phy_84740_i2cdev_read(0,2,0x50,0,100,data8); 6700 */ 6701 int phy_84740_i2cdev_read(int unit, soc_port_t port, int dev_addr, /* 7 bit I2C bus device address */ 6702 int offset, /* starting data address to read */ 6703 int nbytes, /* number of bytes to read */ 6704 uint8 *read_array) 6705 { /* buffer to hold retrieved data */ 6706 return _phy_84740_bsc_rw(unit, port, dev_addr, PHY84740_I2CDEV_READ, 6707 offset, nbytes, (void *)read_array, 6708 PHY84740_READ_START_ADDR); 6709 6710 } 6711 6712 /* 6713 * Write to a slave device such as NVRAM/EEPROM connected to the 84740's I2C 6714 * interface. This function will be mainly used for diagnostic or workaround 6715 * purpose. 6716 * Note: 6717 * The size of write_array buffer should be equal to the parameter nbytes. 6718 * The EEPROM may limit the maximun write size to 16 bytes 6719 * usage example: 6720 * Write to first 100 byte space of the non-volatile storage device with 6721 * I2C bus device address 0x50(default SPF eeprom I2C address) on unit 0, 6722 * port 2, with written data specified in array data8. 6723 * uint8 data8[100]; 6724 * *** initialize the data8 array with written data *** 6725 * 6726 * phy_84740_i2cdev_write(0,2,0x50,0,100,data8); 6727 */ 6728 6729 int phy_84740_i2cdev_write(int unit, soc_port_t port, int dev_addr, /* I2C bus device address */ 6730 int offset, /* starting data address to write to */ 6731 int nbytes, /* number of bytes to write */ 6732 uint8 *write_array) 6733 { /* buffer to hold written data */ 6734 int j; 6735 int rv = SOC_E_NONE; 6736 6737 for (j = 0; j < (nbytes / PHY84740_BSC_WR_MAX); j++) { 6738 rv = _phy_84740_bsc_rw(unit, port, dev_addr, PHY84740_I2CDEV_WRITE, 6739 offset + j * PHY84740_BSC_WR_MAX, 6740 PHY84740_BSC_WR_MAX, 6741 (void *)(write_array + j * PHY84740_BSC_WR_MAX), 6742 PHY84740_WRITE_START_ADDR); 6743 if (rv != SOC_E_NONE) { 6744 return rv; 6745 } 6746 sal_usleep(20000); 6747 } 6748 if (nbytes % PHY84740_BSC_WR_MAX) { 6749 rv = _phy_84740_bsc_rw(unit, port, dev_addr, PHY84740_I2CDEV_WRITE, 6750 offset + j * PHY84740_BSC_WR_MAX, 6751 nbytes % PHY84740_BSC_WR_MAX, 6752 (void *)(write_array + j * PHY84740_BSC_WR_MAX), 6753 PHY84740_WRITE_START_ADDR); 6754 } 6755 return rv; 6756 } 6757 6758 /* 6759 * Callout interface to phy_84740_i2cdev_read(); 6760 * TBD: Extend to handle max_size > PHY84740_BSC_XFER_MAX. 6761 */ 6762 6763 STATIC int 6764 phy_84740_multi_get(int unit, soc_port_t port, uint32 flags, 6765 uint32 dev_addr, uint32 offset, int max_size, uint8 *data, 6766 int *actual_size) 6767 { 6768 int rv; 6769 6770 rv = phy_84740_i2cdev_read(unit, port, (int)dev_addr, (int)offset, max_size, 6771 data); 6772 6773 if (SOC_FAILURE(rv)) { 6774 *actual_size = 0; 6775 return SOC_E_FAIL; 6776 } 6777 6778 *actual_size = max_size; 6779 return SOC_E_NONE; 6780 } 6781 6782 /* 6783 * Function: 6784 * phy_84740_reg_read 6785 * Purpose: 6786 * Routine to read PHY register 6787 * Parameters: 6788 * uint - BCM unit number 6789 * port - port number 6790 * flags - Flags which specify the register type 6791 * phy_reg_addr - Encoded register address 6792 * phy_data - (OUT) Value read from PHY register 6793 * Note: 6794 * This register read function is not thread safe. Higher level 6795 * function that calls this function must obtain a per port lock 6796 * to avoid overriding register page mapping between threads. 6797 */ 6798 STATIC int 6799 phy_84740_reg_read(int unit, soc_port_t port, uint32 flags, 6800 uint32 phy_reg_addr, uint32 *phy_data) 6801 { 6802 uint16 data16; 6803 uint16 regdata; 6804 phy_ctrl_t *pc; /* PHY software state */ 6805 int rv = SOC_E_NONE; 6806 int rd_cnt; 6807 6808 pc = EXT_PHY_SW_STATE(unit, port); 6809 6810 rd_cnt = 1; 6811 6812 if (flags & SOC_PHY_I2C_DATA8) { 6813 6814 SOC_IF_ERROR_RETURN 6815 (phy_84740_i2cdev_read(unit, port, 6816 SOC_PHY_I2C_DEVAD(phy_reg_addr), 6817 SOC_PHY_I2C_REGAD(phy_reg_addr), 6818 rd_cnt, (uint8 *) &data16)); 6819 *phy_data = *((uint8 *) &data16); 6820 6821 } else if (flags & SOC_PHY_I2C_DATA16) { 6822 /* This operation is generally targeted to access 16-bit device, 6823 * such as PHY IC inside the SFP. However there is no 16-bit 6824 * scratch register space on the device. Use 1.800e 6825 * for this operation. 6826 */ 6827 SOC_IF_ERROR_RETURN 6828 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_I2C_TEMP_RAM, 6829 ®data)); 6830 6831 rv = _phy_84740_bsc_rw(unit, port, 6832 SOC_PHY_I2C_DEVAD(phy_reg_addr), 6833 PHY84740_I2C_OP_TYPE(PHY84740_I2CDEV_READ, 6834 PHY84740_I2C_16BIT), 6835 SOC_PHY_I2C_REGAD(phy_reg_addr), 1, 6836 (void *)&data16, PHY84740_I2C_TEMP_RAM); 6837 6838 *phy_data = data16; 6839 6840 /* restore the ram register value */ 6841 SOC_IF_ERROR_RETURN 6842 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_I2C_TEMP_RAM, 6843 regdata)); 6844 } else { 6845 SOC_IF_ERROR_RETURN(READ_PHY_REG(unit, pc, phy_reg_addr, &data16)); 6846 *phy_data = data16; 6847 } 6848 6849 return rv; 6850 } 6851 6852 /* 6853 * Function: 6854 * phy_84740_reg_write 6855 * Purpose: 6856 * Routine to write PHY register 6857 * Parameters: 6858 * uint - BCM unit number 6859 * port - port number 6860 * flags - Flags which specify the register type 6861 * phy_reg_addr - Encoded register address 6862 * phy_data - Value write to PHY register 6863 * Note: 6864 * This register read function is not thread safe. Higher level 6865 * function that calls this function must obtain a per port lock 6866 * to avoid overriding register page mapping between threads. 6867 */ 6868 STATIC int 6869 phy_84740_reg_write(int unit, soc_port_t port, uint32 flags, 6870 uint32 phy_reg_addr, uint32 phy_data) 6871 { 6872 uint8 data8[4]; 6873 uint16 data16[2]; 6874 uint16 regdata[2]; 6875 phy_ctrl_t *pc; /* PHY software state */ 6876 int rv = SOC_E_NONE; 6877 int wr_cnt; 6878 6879 pc = EXT_PHY_SW_STATE(unit, port); 6880 #if defined (BCM_WARM_BOOT_SUPPORT) /* */ 6881 if ( SOC_WARM_BOOT(pc->unit) || SOC_IS_RELOADING(pc->unit) ) { 6882 return SOC_E_NONE; 6883 } 6884 #endif /* BCM_WARM_BOOT_SUPPORT */ 6885 6886 wr_cnt = 1; 6887 6888 if (flags & SOC_PHY_I2C_DATA8) { 6889 data8[0] = (uint8) phy_data; 6890 SOC_IF_ERROR_RETURN 6891 (phy_84740_i2cdev_write(unit, port, 6892 SOC_PHY_I2C_DEVAD(phy_reg_addr), 6893 SOC_PHY_I2C_REGAD(phy_reg_addr), 6894 wr_cnt, data8)); 6895 } else if (flags & SOC_PHY_I2C_DATA16) { 6896 /* This operation is generally targeted to access 16-bit device, 6897 * such as PHY IC inside the SFP. However there is no 16-bit 6898 * scratch register space on the device. Use 1.800e 6899 * for this operation. 6900 */ 6901 /* save the temp ram register */ 6902 SOC_IF_ERROR_RETURN 6903 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_I2C_TEMP_RAM, 6904 ®data[0])); 6905 data16[0] = phy_data; 6906 rv = _phy_84740_bsc_rw(unit, port, 6907 SOC_PHY_I2C_DEVAD(phy_reg_addr), 6908 PHY84740_I2C_OP_TYPE(PHY84740_I2CDEV_WRITE, 6909 PHY84740_I2C_16BIT), 6910 SOC_PHY_I2C_REGAD(phy_reg_addr), wr_cnt, 6911 (void *)data16, PHY84740_I2C_TEMP_RAM); 6912 6913 /* restore the ram register value */ 6914 SOC_IF_ERROR_RETURN 6915 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_I2C_TEMP_RAM, 6916 regdata[0])); 6917 } else { 6918 SOC_IF_ERROR_RETURN 6919 (WRITE_PHY_REG(unit, pc, phy_reg_addr, (uint16) phy_data)); 6920 } 6921 6922 return rv; 6923 } 6924 6925 int 6926 phy_84740_timesync_config_set(int unit, soc_port_t port, 6927 soc_port_phy_timesync_config_t *conf) 6928 { 6929 uint16 rx_control_reg = 0, tx_control_reg = 0, rx_tx_control_reg = 0, 6930 capture_en_reg = 0, rx_ts_cap = 0, tx_ts_cap = 0, 6931 nse_sc_8 = 0, nse_nco_3 = 0, value, mpls_control_reg = 0, temp = 0, 6932 gmode = 0, framesync_mode = 0, syncout_mode = 0, mask = 0, 6933 pulse_1_length, pulse_2_length; 6934 uint32 interval; 6935 int i; 6936 phy_ctrl_t *pc; 6937 6938 pc = EXT_PHY_SW_STATE(unit, port); 6939 6940 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) { 6941 6942 if (conf->flags & SOC_PORT_PHY_TIMESYNC_ENABLE) { 6943 SOC_IF_ERROR_RETURN 6944 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc600, 0x0003)); 6945 nse_sc_8 |= (1U << 12); 6946 } 6947 6948 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE) { 6949 capture_en_reg |= 3U; 6950 } 6951 6952 /* TXRX SOP TS CAPTURE ENABLE reg */ 6953 SOC_IF_ERROR_RETURN 6954 (MODIFY_PHY84740_MMF_PMA_PMD_REG 6955 (unit, pc, 0xc607, capture_en_reg, 3U)); 6956 6957 if (conf->flags & SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE) { 6958 nse_sc_8 |= (1U << 13); 6959 } 6960 6961 /* NSE SC 8 register */ 6962 SOC_IF_ERROR_RETURN 6963 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63a, nse_sc_8, 6964 (1U << 12) | (1U << 13))); 6965 6966 if (conf->flags & SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE) { 6967 rx_tx_control_reg |= (1U << 3); 6968 } 6969 6970 /* RX TX CONTROL register */ 6971 SOC_IF_ERROR_RETURN 6972 (MODIFY_PHY84740_MMF_PMA_PMD_REG 6973 (unit, pc, 0xc61c, rx_tx_control_reg, (1U << 3))); 6974 6975 if (conf->flags & SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE) { 6976 rx_control_reg |= (1U << 3); 6977 tx_control_reg |= (1U << 3); 6978 } 6979 6980 if (conf->flags & SOC_PORT_PHY_TIMESYNC_L2_ENABLE) { 6981 rx_control_reg |= (1U << 2); 6982 tx_control_reg |= (1U << 2); 6983 } 6984 6985 if (conf->flags & SOC_PORT_PHY_TIMESYNC_IP4_ENABLE) { 6986 rx_control_reg |= (1U << 1); 6987 tx_control_reg |= (1U << 1); 6988 } 6989 6990 if (conf->flags & SOC_PORT_PHY_TIMESYNC_IP6_ENABLE) { 6991 rx_control_reg |= (1U << 0); 6992 tx_control_reg |= (1U << 0); 6993 } 6994 6995 /* TX CONTROL register */ 6996 SOC_IF_ERROR_RETURN 6997 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc618, tx_control_reg)); 6998 6999 /* RX CONTROL register */ 7000 SOC_IF_ERROR_RETURN 7001 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc61a, rx_control_reg)); 7002 7003 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT) { 7004 nse_nco_3 &= ~(1U << 14); 7005 } else { 7006 nse_nco_3 |= (1U << 14); 7007 } 7008 7009 /* NSE NCO 3 register */ 7010 SOC_IF_ERROR_RETURN 7011 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc630, nse_nco_3, 7012 (1U << 14))); 7013 7014 if (conf->flags & SOC_PORT_PHY_TIMESYNC_64BIT_TIMESTAMP_ENABLE) { 7015 SOC_IF_ERROR_RETURN 7016 (WRITE_PHY84740_MMF_PMA_PMD_REG 7017 (unit, pc, 0xc609, (uint16) 0x2)); 7018 SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG 7019 (unit, pc, 0xc608, (uint16) 0x2)); 7020 } 7021 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_SYNC) { 7022 tx_ts_cap |= (0x1U << 0); 7023 } 7024 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_DELAY_REQ) { 7025 tx_ts_cap |= (0x1U << 1); 7026 } 7027 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_PDELAY_REQ) { 7028 tx_ts_cap |= (0x1U << 2); 7029 } 7030 if (conf-> 7031 flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_PDELAY_RESP) { 7032 tx_ts_cap |= (0x1U << 3); 7033 } 7034 SOC_IF_ERROR_RETURN 7035 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc602, tx_ts_cap)); 7036 7037 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_SYNC) { 7038 rx_ts_cap |= (0x1U << 0); 7039 } 7040 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_DELAY_REQ) { 7041 rx_ts_cap |= (0x1U << 1); 7042 } 7043 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_PDELAY_REQ) { 7044 rx_ts_cap |= (0x1U << 2); 7045 } 7046 if (conf-> 7047 flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_PDELAY_RESP) { 7048 rx_ts_cap |= (0x1U << 3); 7049 } 7050 SOC_IF_ERROR_RETURN 7051 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc604, rx_ts_cap)); 7052 } 7053 7054 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) { 7055 /* VLAN TAG register */ 7056 SOC_IF_ERROR_RETURN 7057 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc61d, conf->itpid)); 7058 } 7059 7060 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) { 7061 /* OUTER VLAN TAG register */ 7062 SOC_IF_ERROR_RETURN 7063 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc61e, conf->otpid)); 7064 } 7065 7066 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) { 7067 /* INNER VLAN TAG register */ 7068 SOC_IF_ERROR_RETURN 7069 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc61f, conf->otpid2)); 7070 } 7071 7072 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) { 7073 SOC_IF_ERROR_RETURN 7074 (WRITE_PHY84740_MMF_PMA_PMD_REG 7075 (unit, pc, 0xc636, conf->ts_divider & 0xfff)); 7076 } 7077 7078 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) { 7079 SOC_IF_ERROR_RETURN 7080 (WRITE_PHY84740_MMF_PMA_PMD_REG 7081 (unit, pc, 0xc605, conf->rx_link_delay & 0xffff)); 7082 SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG 7083 (unit, pc, 0xc606, 7084 (conf->rx_link_delay >> 16) & 0xffff)); 7085 } 7086 7087 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) { 7088 7089 /* TIME CODE 5 register */ 7090 SOC_IF_ERROR_RETURN 7091 (WRITE_PHY84740_MMF_PMA_PMD_REG 7092 (unit, pc, 0xc610, 7093 (uint16) (conf->original_timecode.nanoseconds & 0xffff))); 7094 7095 /* TIME CODE 4 register */ 7096 SOC_IF_ERROR_RETURN 7097 (WRITE_PHY84740_MMF_PMA_PMD_REG 7098 (unit, pc, 0xc60f, 7099 (uint16) ((conf->original_timecode.nanoseconds >> 16) & 0xffff))); 7100 7101 /* TIME CODE 3 register */ 7102 SOC_IF_ERROR_RETURN 7103 (WRITE_PHY84740_MMF_PMA_PMD_REG 7104 (unit, pc, 0xc60e, 7105 (uint16) (COMPILER_64_LO(conf->original_timecode.seconds) & 7106 0xffff))); 7107 7108 /* TIME CODE 2 register */ 7109 SOC_IF_ERROR_RETURN 7110 (WRITE_PHY84740_MMF_PMA_PMD_REG 7111 (unit, pc, 0xc60d, 7112 (uint16) ((COMPILER_64_LO(conf->original_timecode.seconds) >> 16) 7113 & 0xffff))); 7114 7115 /* TIME CODE 1 register */ 7116 SOC_IF_ERROR_RETURN 7117 (WRITE_PHY84740_MMF_PMA_PMD_REG 7118 (unit, pc, 0xc60c, 7119 (uint16) (COMPILER_64_HI(conf->original_timecode.seconds) & 7120 0xffff))); 7121 } 7122 7123 mask = 0; 7124 7125 /* NSE SC 8 register */ 7126 7127 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) { 7128 _phy_84740_encode_gmode(conf->gmode, &gmode); 7129 mask |= (0x3 << 14); 7130 } 7131 7132 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) { 7133 _phy_84740_encode_framesync_mode(conf->framesync.mode, &framesync_mode); 7134 mask |= (0xf << 2) | (0x1 << 11) | (0x1 << 6); 7135 SOC_IF_ERROR_RETURN 7136 (WRITE_PHY84740_MMF_PMA_PMD_REG 7137 (unit, pc, 0xc63c, conf->framesync.length_threshold)); 7138 SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG 7139 (unit, pc, 0xc63b, conf->framesync.event_offset)); 7140 } 7141 7142 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) { 7143 _phy_84740_encode_syncout_mode(conf->syncout.mode, &syncout_mode); 7144 mask |= (0x3 << 0); 7145 7146 /* Divide by 6.4 without floating point */ 7147 interval = (conf->syncout.interval * 10) / 64; 7148 pulse_1_length = (conf->syncout.pulse_1_length * 10) / 64; 7149 pulse_2_length = (conf->syncout.pulse_2_length * 10) / 64; 7150 7151 SOC_IF_ERROR_RETURN 7152 (WRITE_PHY84740_MMF_PMA_PMD_REG 7153 (unit, pc, 0xc635, interval & 0xffff)); 7154 SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG 7155 (unit, pc, 0xc634, 7156 ((pulse_2_length & 0x3) << 14) | ((interval >> 16) 7157 & 0x3fff))); 7158 SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG 7159 (unit, pc, 0xc633, 7160 ((pulse_1_length & 0x1ff) << 7) | 7161 ((pulse_2_length >> 2) & 0x7f))); 7162 7163 SOC_IF_ERROR_RETURN 7164 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc639, 7165 (uint16) (COMPILER_64_LO 7166 (conf->syncout. 7167 syncout_ts) & 0xfff0))); 7168 SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG 7169 (unit, pc, 0xc638, 7170 (uint16) ((COMPILER_64_LO(conf->syncout.syncout_ts) 7171 >> 16) & 0xffff))); 7172 SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG 7173 (unit, pc, 0xc637, 7174 (uint16) (COMPILER_64_HI(conf->syncout.syncout_ts) 7175 & 0xffff))); 7176 } 7177 7178 SOC_IF_ERROR_RETURN 7179 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 7180 0xc63a, 7181 (gmode << 14) | 7182 ((framesync_mode & 0x2) ? (1U << 11) : (1U << 6)) | /* if bits 1 or 2 are set, turn off syncout */ 7183 (framesync_mode << 2) | 7184 (syncout_mode << 0), 7185 mask)); 7186 7187 mask = 0; 7188 7189 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) { 7190 /* RX TS OFFSET register */ 7191 SOC_IF_ERROR_RETURN 7192 (WRITE_PHY84740_MMF_PMA_PMD_REG 7193 (unit, pc, 0xc60b, (uint16) (conf->rx_timestamp_offset & 0xffff))); 7194 mask |= 0xf000; 7195 } 7196 7197 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) { 7198 mask |= 0x0fff; 7199 } 7200 7201 /* TXRX TS OFFSET register */ 7202 SOC_IF_ERROR_RETURN 7203 (MODIFY_PHY84740_MMF_PMA_PMD_REG 7204 (unit, pc, 0xc60a, 7205 (uint16) (((conf->rx_timestamp_offset & 0xf0000) >> 4) | (conf-> 7206 tx_timestamp_offset 7207 & 0xfff)), 7208 mask)); 7209 value = 0; 7210 mask = 0; 7211 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) { 7212 _phy_84740_encode_egress_message_mode(conf->tx_sync_mode, 0, &value); 7213 mask |= 0x3 << 0; 7214 } 7215 7216 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) { 7217 _phy_84740_encode_egress_message_mode(conf->tx_delay_request_mode, 2, 7218 &value); 7219 mask |= 0x3 << 2; 7220 } 7221 7222 if (conf-> 7223 validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) { 7224 _phy_84740_encode_egress_message_mode(conf->tx_pdelay_request_mode, 4, 7225 &value); 7226 mask |= 0x3 << 4; 7227 } 7228 7229 if (conf-> 7230 validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) { 7231 _phy_84740_encode_egress_message_mode(conf->tx_pdelay_response_mode, 6, 7232 &value); 7233 mask |= 0x3 << 6; 7234 } 7235 7236 /* TX EVENT MESSAGE MODE SEL register */ 7237 SOC_IF_ERROR_RETURN 7238 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc601, value, mask)); 7239 7240 value = 0; 7241 mask = 0; 7242 7243 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) { 7244 _phy_84740_encode_ingress_message_mode(conf->rx_sync_mode, 0, &value); 7245 mask |= 0x3 << 0; 7246 } 7247 7248 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) { 7249 _phy_84740_encode_ingress_message_mode(conf->rx_delay_request_mode, 2, 7250 &value); 7251 mask |= 0x3 << 2; 7252 } 7253 7254 if (conf-> 7255 validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) { 7256 _phy_84740_encode_ingress_message_mode(conf->rx_pdelay_request_mode, 4, 7257 &value); 7258 mask |= 0x3 << 4; 7259 } 7260 7261 if (conf-> 7262 validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) { 7263 _phy_84740_encode_ingress_message_mode(conf->rx_pdelay_response_mode, 6, 7264 &value); 7265 mask |= 0x3 << 6; 7266 } 7267 7268 /* RX EVENT MESSAGE MODE SEL register */ 7269 SOC_IF_ERROR_RETURN 7270 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc603, value, mask)); 7271 7272 if (conf-> 7273 validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) { 7274 7275 /* Initial ref phase [15:0] */ 7276 SOC_IF_ERROR_RETURN 7277 (WRITE_PHY84740_MMF_PMA_PMD_REG 7278 (unit, pc, 0xc623, 7279 (uint16) (COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) & 7280 0xffff))); 7281 7282 /* Initial ref phase [31:16] */ 7283 SOC_IF_ERROR_RETURN 7284 (WRITE_PHY84740_MMF_PMA_PMD_REG 7285 (unit, pc, 0xc622, 7286 (uint16) ((COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) >> 16) & 7287 0xffff))); 7288 7289 /* Initial ref phase [47:32] */ 7290 SOC_IF_ERROR_RETURN 7291 (WRITE_PHY84740_MMF_PMA_PMD_REG 7292 (unit, pc, 0xc621, 7293 (uint16) (COMPILER_64_HI(conf->phy_1588_dpll_ref_phase) & 7294 0xffff))); 7295 } 7296 7297 if (conf-> 7298 validity_mask & 7299 SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) { 7300 SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG 7301 (unit, pc, 0xc625, 7302 conf->phy_1588_dpll_ref_phase_delta & 0xffff)); 7303 SOC_IF_ERROR_RETURN(WRITE_PHY84740_MMF_PMA_PMD_REG 7304 (unit, pc, 0xc624, 7305 (conf-> 7306 phy_1588_dpll_ref_phase_delta >> 16) & 0xffff)); 7307 } 7308 7309 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) { 7310 /* DPLL K1 */ 7311 SOC_IF_ERROR_RETURN 7312 (WRITE_PHY84740_MMF_PMA_PMD_REG 7313 (unit, pc, 0xc626, conf->phy_1588_dpll_k1 & 0xff)); 7314 } 7315 7316 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) { 7317 /* DPLL K2 */ 7318 SOC_IF_ERROR_RETURN 7319 (WRITE_PHY84740_MMF_PMA_PMD_REG 7320 (unit, pc, 0xc627, conf->phy_1588_dpll_k2 & 0xff)); 7321 } 7322 7323 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) { 7324 /* DPLL K3 */ 7325 SOC_IF_ERROR_RETURN 7326 (WRITE_PHY84740_MMF_PMA_PMD_REG 7327 (unit, pc, 0xc628, conf->phy_1588_dpll_k3 & 0xff)); 7328 } 7329 7330 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL) { 7331 7332 /* MPLS controls */ 7333 if (conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_ENABLE) { 7334 mpls_control_reg |= (1U << 7) | (1U << 3); 7335 } 7336 7337 if (conf->mpls_control. 7338 flags & SOC_PORT_PHY_TIMESYNC_MPLS_ENTROPY_ENABLE) { 7339 mpls_control_reg |= (1U << 6) | (1U << 2); 7340 } 7341 7342 if (conf->mpls_control. 7343 flags & SOC_PORT_PHY_TIMESYNC_MPLS_SPECIAL_LABEL_ENABLE) { 7344 mpls_control_reg |= (1U << 4); 7345 } 7346 7347 if (conf->mpls_control. 7348 flags & SOC_PORT_PHY_TIMESYNC_MPLS_CONTROL_WORD_ENABLE) { 7349 mpls_control_reg |= (1U << 5) | (1U << 1); 7350 } 7351 SOC_IF_ERROR_RETURN 7352 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc651, mpls_control_reg, 7353 (1U << 7) | (1U << 3) | (1U << 6) | 7354 (1U << 2) | (1U << 4) | (1U << 5) | 7355 (1U << 1))); 7356 7357 /* special label [19:16] */ 7358 SOC_IF_ERROR_RETURN 7359 (WRITE_PHY84740_MMF_PMA_PMD_REG 7360 (unit, pc, 0xc653, 7361 (uint16) ((conf->mpls_control.special_label >> 16) & 0xf))); 7362 7363 /* special label [15:0] */ 7364 SOC_IF_ERROR_RETURN 7365 (WRITE_PHY84740_MMF_PMA_PMD_REG 7366 (unit, pc, 0xc652, 7367 (uint16) (conf->mpls_control.special_label & 0xffff))); 7368 7369 for (i = 0; i < 10; i++) { 7370 SOC_IF_ERROR_RETURN 7371 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 7372 0xc654 + i, 7373 (uint16) (conf->mpls_control.labels[i].value & 0xffff))); 7374 SOC_IF_ERROR_RETURN 7375 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 7376 0xc661 + i, 7377 (uint16) (conf->mpls_control.labels[i].mask & 0xffff))); 7378 } 7379 7380 SOC_IF_ERROR_RETURN 7381 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 7382 0xc65e, 7383 (uint16) (((conf->mpls_control.labels[3].value >> 4) & 0xf000) | 7384 ((conf->mpls_control.labels[2].value >> 8) & 0x0f00) | 7385 ((conf->mpls_control.labels[1].value >> 12) & 0x00f0) | 7386 ((conf->mpls_control.labels[0].value >> 16) & 0x000f)))); 7387 7388 SOC_IF_ERROR_RETURN 7389 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 7390 0xc65f, 7391 (uint16) (((conf->mpls_control.labels[7].value >> 4) & 0xf000) | 7392 ((conf->mpls_control.labels[6].value >> 8) & 0x0f00) | 7393 ((conf->mpls_control.labels[5].value >> 12) & 0x00f0) | 7394 ((conf->mpls_control.labels[4].value >> 16) & 0x000f)))); 7395 7396 SOC_IF_ERROR_RETURN 7397 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 7398 0xc660, 7399 (uint16) (((conf->mpls_control.labels[9].value >> 12) & 0x00f0) | 7400 ((conf->mpls_control.labels[8].value >> 16) & 0x000f)))); 7401 SOC_IF_ERROR_RETURN 7402 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 7403 0xc66b, 7404 (uint16) (((conf->mpls_control.labels[3].mask >> 4) & 0xf000) | 7405 ((conf->mpls_control.labels[2].mask >> 8) & 0x0f00) | 7406 ((conf->mpls_control.labels[1].mask >> 12) & 0x00f0) | 7407 ((conf->mpls_control.labels[0].mask >> 16) & 0x000f)))); 7408 7409 SOC_IF_ERROR_RETURN 7410 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 7411 0xc66c, 7412 (uint16) (((conf->mpls_control.labels[7].mask >> 4) & 0xf000) | 7413 ((conf->mpls_control.labels[6].mask >> 8) & 0x0f00) | 7414 ((conf->mpls_control.labels[5].mask >> 12) & 0x00f0) | 7415 ((conf->mpls_control.labels[4].mask >> 16) & 0x000f)))); 7416 7417 SOC_IF_ERROR_RETURN 7418 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 7419 0xc66d, 7420 (uint16) (((conf->mpls_control.labels[9].mask >> 12) & 0x00f0) | 7421 ((conf->mpls_control.labels[8].mask >> 16) & 0x000f)))); 7422 7423 /* label flags */ 7424 temp = 0; 7425 for (i = 0; i < 8; i++) { 7426 temp |= 7427 conf->mpls_control.labels[i].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT ? (0x2 << (i << 1)) : 0; 7428 temp |= 7429 (conf->mpls_control.labels[i].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN) ? (0x1 << (i << 1)) : 0; 7430 } 7431 7432 SOC_IF_ERROR_RETURN 7433 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc66e, temp)); 7434 7435 temp = 0; 7436 for (i = 0; i < 2; i++) { 7437 temp |= 7438 (conf->mpls_control.labels[i + 8].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT) ? (0x2 << (i << 1)) : 0; 7439 temp |= 7440 (conf->mpls_control.labels[i + 8].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN) ? (0x1 << (i << 1)) : 0; 7441 } 7442 7443 SOC_IF_ERROR_RETURN 7444 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc66f, temp)); 7445 } 7446 return SOC_E_NONE; 7447 } 7448 7449 int 7450 phy_84740_timesync_config_get(int unit, soc_port_t port, 7451 soc_port_phy_timesync_config_t *conf) 7452 { 7453 uint16 rx_tx_control_reg = 0, tx_control_reg = 0, 7454 en_control_reg = 0, capture_en_reg = 0, rx_ts_cap = 0, tx_ts_cap = 0, 7455 nse_sc_8 = 0, nse_nco_3 = 7456 0, temp1, temp2, temp3, value, mpls_control_reg; 7457 soc_port_phy_timesync_global_mode_t gmode = SOC_PORT_PHY_TIMESYNC_MODE_FREE; 7458 soc_port_phy_timesync_framesync_mode_t framesync_mode = 7459 SOC_PORT_PHY_TIMESYNC_FRAMESYNC_NONE; 7460 soc_port_phy_timesync_syncout_mode_t syncout_mode = 7461 SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE; 7462 int i; 7463 phy_ctrl_t *pc; 7464 7465 pc = EXT_PHY_SW_STATE(unit, port); 7466 7467 conf->flags = 0; 7468 7469 /* NSE SC 8 register */ 7470 SOC_IF_ERROR_RETURN 7471 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63a, &nse_sc_8)); 7472 7473 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) { 7474 /* SLICE ENABLE CONTROL register */ 7475 SOC_IF_ERROR_RETURN 7476 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc600, &en_control_reg)); 7477 7478 if (en_control_reg & 1U) { 7479 conf->flags |= SOC_PORT_PHY_TIMESYNC_ENABLE; 7480 } 7481 7482 /* TXRX SOP TS CAPTURE ENABLE reg */ 7483 SOC_IF_ERROR_RETURN 7484 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc607, &capture_en_reg)); 7485 7486 if (capture_en_reg & 1U) { 7487 conf->flags |= SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE; 7488 } 7489 7490 /* NSE SC 8 register */ 7491 /* SOC_IF_ERROR_RETURN 7492 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63a, &nse_sc_8)); 7493 */ 7494 7495 if (nse_sc_8 & (1U << 13)) { 7496 conf->flags |= SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE; 7497 } 7498 7499 /* RX TX CONTROL register */ 7500 SOC_IF_ERROR_RETURN 7501 (READ_PHY84740_MMF_PMA_PMD_REG 7502 (unit, pc, 0xc61c, &rx_tx_control_reg)); 7503 7504 if (rx_tx_control_reg & (1U << 3)) { 7505 conf->flags |= SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE; 7506 } 7507 7508 /* TX CONTROL register */ 7509 SOC_IF_ERROR_RETURN 7510 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc618, &tx_control_reg)); 7511 7512 if (tx_control_reg & (1U << 3)) { 7513 conf->flags |= SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE; 7514 } 7515 7516 if (tx_control_reg & (1U << 2)) { 7517 conf->flags |= SOC_PORT_PHY_TIMESYNC_L2_ENABLE; 7518 } 7519 7520 if (tx_control_reg & (1U << 1)) { 7521 conf->flags |= SOC_PORT_PHY_TIMESYNC_IP4_ENABLE; 7522 } 7523 7524 if (tx_control_reg & (1U << 0)) { 7525 conf->flags |= SOC_PORT_PHY_TIMESYNC_IP6_ENABLE; 7526 } 7527 7528 SOC_IF_ERROR_RETURN 7529 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc630, &nse_nco_3)); 7530 7531 if (!(nse_nco_3 & (1U << 14))) { 7532 conf->flags |= SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT; 7533 } 7534 7535 SOC_IF_ERROR_RETURN 7536 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc609, &temp1)); 7537 SOC_IF_ERROR_RETURN 7538 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc608, &temp2)); 7539 if (temp2 == 0x2 && temp1 == 0x2) { 7540 conf->flags |= SOC_PORT_PHY_TIMESYNC_64BIT_TIMESTAMP_ENABLE; 7541 } 7542 SOC_IF_ERROR_RETURN 7543 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc602, &tx_ts_cap)); 7544 if (tx_ts_cap & (0x1U << 0)) { 7545 conf->flags |= SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_SYNC; 7546 } 7547 if (tx_ts_cap & (0x1U << 1)) { 7548 conf->flags |= SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_DELAY_REQ; 7549 } 7550 if (tx_ts_cap & (0x1U << 2)) { 7551 conf->flags |= 7552 SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_PDELAY_REQ; 7553 } 7554 if (tx_ts_cap & (0x1U << 3)) { 7555 conf->flags |= 7556 SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_TX_PDELAY_RESP; 7557 } 7558 7559 SOC_IF_ERROR_RETURN 7560 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc604, &rx_ts_cap)); 7561 if (rx_ts_cap & (0x1U << 0)) { 7562 conf->flags |= SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_SYNC; 7563 } 7564 if (rx_ts_cap & (0x1U << 1)) { 7565 conf->flags |= SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_DELAY_REQ; 7566 } 7567 if (rx_ts_cap & (0x1U << 2)) { 7568 conf->flags |= 7569 SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_PDELAY_REQ; 7570 } 7571 if (rx_ts_cap & (0x1U << 3)) { 7572 conf->flags |= 7573 SOC_PORT_PHY_TIMESYNC_CAPTURE_TIMESTAMP_RX_PDELAY_RESP; 7574 } 7575 } 7576 7577 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) { 7578 _phy_84740_decode_gmode((nse_sc_8 >> 14), &gmode); 7579 conf->gmode = gmode; 7580 } 7581 7582 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) { 7583 _phy_84740_decode_framesync_mode((nse_sc_8 >> 2), &framesync_mode); 7584 conf->framesync.mode = framesync_mode; 7585 SOC_IF_ERROR_RETURN 7586 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63c, &temp1)); 7587 SOC_IF_ERROR_RETURN 7588 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63b, &temp2)); 7589 conf->framesync.length_threshold = temp1; 7590 conf->framesync.event_offset = temp2; 7591 } 7592 7593 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) { 7594 _phy_84740_decode_syncout_mode((nse_sc_8 >> 0), &syncout_mode); 7595 conf->syncout.mode = syncout_mode; 7596 7597 SOC_IF_ERROR_RETURN 7598 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc635, &temp1)); 7599 SOC_IF_ERROR_RETURN 7600 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc634, &temp2)); 7601 SOC_IF_ERROR_RETURN 7602 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc633, &temp3)); 7603 /* Multiply by 6.4 without floating point */ 7604 conf->syncout.pulse_1_length = (((temp3 >> 7) & 0x1ff) * 64) / 10; 7605 conf->syncout.pulse_2_length = 7606 ((((temp3 & 0x7f) << 2) | ((temp2 >> 14) & 0x3)) * 64) / 10; 7607 conf->syncout.interval = ((((temp2 & 0x3fff) << 16) | temp1) * 64) / 10; 7608 7609 SOC_IF_ERROR_RETURN 7610 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc639, &temp1)); 7611 SOC_IF_ERROR_RETURN 7612 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc638, &temp2)); 7613 SOC_IF_ERROR_RETURN 7614 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc637, &temp3)); 7615 7616 COMPILER_64_SET(conf->syncout.syncout_ts, ((uint32) temp3), 7617 (((uint32) temp2 << 16) | ((uint32) temp1))); 7618 } 7619 7620 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) { 7621 /* VLAN TAG register */ 7622 SOC_IF_ERROR_RETURN 7623 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc61d, &conf->itpid)); 7624 } 7625 7626 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) { 7627 /* OUTER VLAN TAG register */ 7628 SOC_IF_ERROR_RETURN 7629 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc61e, &conf->otpid)); 7630 } 7631 7632 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) { 7633 /* INNER VLAN TAG register */ 7634 SOC_IF_ERROR_RETURN 7635 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc61f, &conf->otpid2)); 7636 } 7637 7638 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) { 7639 SOC_IF_ERROR_RETURN 7640 (READ_PHY84740_MMF_PMA_PMD_REG 7641 (unit, pc, 0xc636, &conf->ts_divider)); 7642 conf->ts_divider &= 0xfff; 7643 } 7644 7645 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) { 7646 SOC_IF_ERROR_RETURN 7647 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc605, &temp1)); 7648 SOC_IF_ERROR_RETURN 7649 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc606, &temp2)); 7650 7651 conf->rx_link_delay = ((uint32) temp2 << 16) | temp1; 7652 } 7653 7654 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) { 7655 /* TIME CODE 5 register */ 7656 SOC_IF_ERROR_RETURN 7657 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc610, &temp1)); 7658 7659 /* TIME CODE 4 register */ 7660 SOC_IF_ERROR_RETURN 7661 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc60f, &temp2)); 7662 7663 conf->original_timecode.nanoseconds = ((uint32) temp2 << 16) | temp1; 7664 7665 /* TIME CODE 3 register */ 7666 SOC_IF_ERROR_RETURN 7667 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc60e, &temp1)); 7668 7669 /* TIME CODE 2 register */ 7670 SOC_IF_ERROR_RETURN 7671 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc60d, &temp2)); 7672 7673 /* TIME CODE 1 register */ 7674 SOC_IF_ERROR_RETURN 7675 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc60c, &temp3)); 7676 7677 /* conf->original_timecode.seconds = ((uint64)temp3 << 32) | ((uint32)temp2 << 16) | temp1; */ 7678 7679 COMPILER_64_SET(conf->original_timecode.seconds, ((uint32) temp3), 7680 (((uint32) temp2 << 16) | ((uint32) temp1))); 7681 } 7682 7683 /* TXRX TS OFFSET register */ 7684 SOC_IF_ERROR_RETURN 7685 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc60a, &temp1)); 7686 7687 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) { 7688 /* RX TS OFFSET register */ 7689 SOC_IF_ERROR_RETURN 7690 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc60b, &temp2)); 7691 conf->rx_timestamp_offset = (((uint32) (temp1 & 0xf000)) << 4) | temp2; 7692 } 7693 7694 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) { 7695 conf->tx_timestamp_offset = temp1 & 0xfff; 7696 } 7697 7698 /* TX EVENT MESSAGE MODE SEL register */ 7699 SOC_IF_ERROR_RETURN 7700 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc601, &value)); 7701 7702 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) { 7703 _phy_84740_decode_egress_message_mode(value, 0, &conf->tx_sync_mode); 7704 } 7705 7706 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) { 7707 _phy_84740_decode_egress_message_mode(value, 2, 7708 &conf->tx_delay_request_mode); 7709 } 7710 7711 if (conf-> 7712 validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) { 7713 _phy_84740_decode_egress_message_mode(value, 4, 7714 &conf->tx_pdelay_request_mode); 7715 } 7716 7717 if (conf-> 7718 validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) { 7719 _phy_84740_decode_egress_message_mode(value, 6, 7720 &conf->tx_pdelay_response_mode); 7721 } 7722 7723 /* RX EVENT MESSAGE MODE SEL register */ 7724 SOC_IF_ERROR_RETURN 7725 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc603, &value)); 7726 7727 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) { 7728 _phy_84740_decode_ingress_message_mode(value, 0, &conf->rx_sync_mode); 7729 } 7730 7731 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) { 7732 _phy_84740_decode_ingress_message_mode(value, 2, 7733 &conf->rx_delay_request_mode); 7734 } 7735 7736 if (conf-> 7737 validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) { 7738 _phy_84740_decode_ingress_message_mode(value, 4, 7739 &conf->rx_pdelay_request_mode); 7740 } 7741 7742 if (conf-> 7743 validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) { 7744 _phy_84740_decode_ingress_message_mode(value, 6, 7745 &conf->rx_pdelay_response_mode); 7746 } 7747 7748 if (conf-> 7749 validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) { 7750 /* Initial ref phase [15:0] */ 7751 SOC_IF_ERROR_RETURN 7752 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc623, &temp1)); 7753 7754 /* Initial ref phase [31:16] */ 7755 SOC_IF_ERROR_RETURN 7756 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc622, &temp2)); 7757 7758 /* Initial ref phase [47:32] */ 7759 SOC_IF_ERROR_RETURN 7760 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc621, &temp3)); 7761 7762 /* conf->phy_1588_dpll_phase_initial = ((uint64)temp3 << 32) | ((uint32)temp2 << 16) | temp1; */ 7763 7764 COMPILER_64_SET(conf->phy_1588_dpll_ref_phase, ((uint32) temp3), 7765 (((uint32) temp2 << 16) | ((uint32) temp1))); 7766 } 7767 if (conf-> 7768 validity_mask & 7769 SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) { 7770 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 7771 (unit, pc, 0xc625, &temp1)); 7772 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 7773 (unit, pc, 0xc624, &temp2)); 7774 7775 conf->phy_1588_dpll_ref_phase_delta = ((uint32) temp2 << 16) | temp1; 7776 } 7777 7778 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) { 7779 /* DPLL K1 */ 7780 SOC_IF_ERROR_RETURN 7781 (READ_PHY84740_MMF_PMA_PMD_REG 7782 (unit, pc, 0xc626, &conf->phy_1588_dpll_k1)); 7783 conf->phy_1588_dpll_k1 &= 0xff; 7784 } 7785 7786 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) { 7787 /* DPLL K2 */ 7788 SOC_IF_ERROR_RETURN 7789 (READ_PHY84740_MMF_PMA_PMD_REG 7790 (unit, pc, 0xc627, &conf->phy_1588_dpll_k2)); 7791 conf->phy_1588_dpll_k2 &= 0xff; 7792 } 7793 7794 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) { 7795 /* DPLL K3 */ 7796 SOC_IF_ERROR_RETURN 7797 (READ_PHY84740_MMF_PMA_PMD_REG 7798 (unit, pc, 0xc628, &conf->phy_1588_dpll_k3)); 7799 conf->phy_1588_dpll_k3 &= 0xff; 7800 } 7801 7802 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL) { 7803 SOC_IF_ERROR_RETURN 7804 (READ_PHY84740_MMF_PMA_PMD_REG 7805 (unit, pc, 0xc651, &mpls_control_reg)); 7806 7807 conf->mpls_control.flags = 0; 7808 7809 if (mpls_control_reg & (1U << 7)) { 7810 conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_ENABLE; 7811 } 7812 7813 if (mpls_control_reg & (1U << 6)) { 7814 conf->mpls_control.flags |= 7815 SOC_PORT_PHY_TIMESYNC_MPLS_ENTROPY_ENABLE; 7816 } 7817 7818 if (mpls_control_reg & (1U << 4)) { 7819 conf->mpls_control.flags |= 7820 SOC_PORT_PHY_TIMESYNC_MPLS_SPECIAL_LABEL_ENABLE; 7821 } 7822 7823 if (mpls_control_reg & (1U << 5)) { 7824 conf->mpls_control.flags |= 7825 SOC_PORT_PHY_TIMESYNC_MPLS_CONTROL_WORD_ENABLE; 7826 } 7827 7828 /* special label [19:16] */ 7829 SOC_IF_ERROR_RETURN 7830 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc653, &temp2)); 7831 7832 /* special label [15:0] */ 7833 SOC_IF_ERROR_RETURN 7834 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc652, &temp1)); 7835 7836 conf->mpls_control.special_label = 7837 ((uint32) (temp2 & 0x0f) << 16) | temp1; 7838 7839 for (i = 0; i < 10; i++) { 7840 7841 SOC_IF_ERROR_RETURN 7842 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc654 + i, &temp1)); 7843 conf->mpls_control.labels[i].value = temp1; 7844 7845 SOC_IF_ERROR_RETURN 7846 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc661 + i, &temp1)); 7847 conf->mpls_control.labels[i].mask = temp1; 7848 } 7849 7850 /* now get [19:16] of labels */ 7851 SOC_IF_ERROR_RETURN 7852 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc65e, &temp1)); 7853 7854 conf->mpls_control.labels[0].value |= ((uint32) (temp1 & 0x000f) << 16); 7855 conf->mpls_control.labels[1].value |= ((uint32) (temp1 & 0x00f0) << 12); 7856 conf->mpls_control.labels[2].value |= ((uint32) (temp1 & 0x0f00) << 8); 7857 conf->mpls_control.labels[3].value |= ((uint32) (temp1 & 0xf000) << 4); 7858 7859 SOC_IF_ERROR_RETURN 7860 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc65f, &temp1)); 7861 7862 conf->mpls_control.labels[4].value |= ((uint32) (temp1 & 0x000f) << 16); 7863 conf->mpls_control.labels[5].value |= ((uint32) (temp1 & 0x00f0) << 12); 7864 conf->mpls_control.labels[6].value |= ((uint32) (temp1 & 0x0f00) << 8); 7865 conf->mpls_control.labels[7].value |= ((uint32) (temp1 & 0xf000) << 4); 7866 7867 SOC_IF_ERROR_RETURN 7868 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc660, &temp1)); 7869 7870 conf->mpls_control.labels[8].value |= ((uint32) (temp1 & 0x000f) << 16); 7871 conf->mpls_control.labels[9].value |= ((uint32) (temp1 & 0x00f0) << 12); 7872 7873 /* now get [19:16] of masks */ 7874 SOC_IF_ERROR_RETURN 7875 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc66b, &temp1)); 7876 7877 conf->mpls_control.labels[0].mask |= ((uint32) (temp1 & 0x000f) << 16); 7878 conf->mpls_control.labels[1].mask |= ((uint32) (temp1 & 0x00f0) << 12); 7879 conf->mpls_control.labels[2].mask |= ((uint32) (temp1 & 0x0f00) << 8); 7880 conf->mpls_control.labels[3].mask |= ((uint32) (temp1 & 0xf000) << 4); 7881 7882 SOC_IF_ERROR_RETURN 7883 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc66c, &temp1)); 7884 conf->mpls_control.labels[4].mask |= ((uint32) (temp1 & 0x000f) << 16); 7885 conf->mpls_control.labels[5].mask |= ((uint32) (temp1 & 0x00f0) << 12); 7886 conf->mpls_control.labels[6].mask |= ((uint32) (temp1 & 0x0f00) << 8); 7887 conf->mpls_control.labels[7].mask |= ((uint32) (temp1 & 0xf000) << 4); 7888 7889 SOC_IF_ERROR_RETURN 7890 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc66d, &temp1)); 7891 7892 conf->mpls_control.labels[8].mask |= ((uint32) (temp1 & 0x000f) << 16); 7893 conf->mpls_control.labels[9].mask |= ((uint32) (temp1 & 0x00f0) << 12); 7894 7895 /* label flags */ 7896 SOC_IF_ERROR_RETURN 7897 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc66e, &temp1)); 7898 for (i = 0; i < 8; i++) { 7899 conf->mpls_control.labels[i].flags |= 7900 temp1 & (0x2 << (i << 1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT: 0; 7901 conf->mpls_control.labels[i].flags |= 7902 temp1 & (0x1 << (i << 1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN: 0; 7903 } 7904 SOC_IF_ERROR_RETURN 7905 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc66f, &temp2)); 7906 for (i = 0; i < 2; i++) { 7907 conf->mpls_control.labels[i + 8].flags |= 7908 temp2 & (0x2 << (i << 1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT: 0; 7909 conf->mpls_control.labels[i + 8].flags |= 7910 temp2 & (0x1 << (i << 1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN: 0; 7911 } 7912 7913 } 7914 return SOC_E_NONE; 7915 } 7916 7917 int 7918 phy_84740_timesync_control_set(int unit, soc_port_t port, 7919 soc_port_control_phy_timesync_t type, 7920 uint64 value) 7921 { 7922 uint16 temp1, temp2; 7923 uint32 value0; 7924 phy_ctrl_t *pc; 7925 7926 pc = EXT_PHY_SW_STATE(unit, port); 7927 7928 switch (type) { 7929 7930 case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP: 7931 case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP: 7932 return SOC_E_FAIL; 7933 7934 case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND: 7935 SOC_IF_ERROR_RETURN 7936 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 7937 0xc62f, 7938 (uint16) (COMPILER_64_LO(value) & 0xffff))); 7939 SOC_IF_ERROR_RETURN 7940 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 7941 0xc62e, 7942 (uint16) ((COMPILER_64_LO(value) >> 16) & 0xffff))); 7943 break; 7944 7945 case SOC_PORT_CONTROL_PHY_TIMESYNC_FRAMESYNC: 7946 7947 SOC_IF_ERROR_RETURN 7948 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63a, &temp1)); 7949 temp2 = ((temp1 | 7950 (0x3 << 14) | 7951 (0x1 << 12)) & 7952 ~(0xf << 2)) | 7953 (0x1 << 5); 7954 SOC_IF_ERROR_RETURN 7955 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63a, temp2)); 7956 sal_usleep(1); 7957 temp2 &= ~((0x1 << 5) | (0x1 << 12)); 7958 SOC_IF_ERROR_RETURN 7959 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63a, temp2)); 7960 sal_usleep(1); 7961 SOC_IF_ERROR_RETURN 7962 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63a, temp1)); 7963 break; 7964 7965 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME: 7966 /* COMPILER_64_SHR(value, 4); *//* shifting 4 bits extra, not required */ 7967 SOC_IF_ERROR_RETURN 7968 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 7969 0xc632, 7970 (uint16) (COMPILER_64_LO(value) & 0xffff))); 7971 SOC_IF_ERROR_RETURN 7972 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 7973 0xc631, 7974 (uint16) ((COMPILER_64_LO(value) >> 16) & 7975 0xffff))); 7976 SOC_IF_ERROR_RETURN 7977 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 7978 0xc630, 7979 (uint16) COMPILER_64_HI(value), 7980 0x0fff)); 7981 break; 7982 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL: 7983 temp1 = 0; 7984 temp2 = 0; 7985 7986 value0 = COMPILER_64_LO(value); 7987 7988 if (value0 & SOC_PORT_PHY_TIMESYNC_TN_LOAD) { 7989 temp1 |= 1U << 11; 7990 } 7991 if (value0 & SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD) { 7992 temp2 |= 1U << 11; 7993 } 7994 if (value0 & SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD) { 7995 temp1 |= 1U << 10; 7996 } 7997 if (value0 & SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD) { 7998 temp2 |= 1U << 10; 7999 } 8000 if (value0 & SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD) { 8001 temp1 |= 1U << 9; 8002 } 8003 if (value0 & SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD) { 8004 temp2 |= 1U << 9; 8005 } 8006 if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD) { 8007 temp1 |= 1U << 8; 8008 } 8009 if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD) { 8010 temp2 |= 1U << 8; 8011 } 8012 if (value0 & SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD) { 8013 temp1 |= 1U << 7; 8014 } 8015 if (value0 & SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD) { 8016 temp2 |= 1U << 7; 8017 } 8018 if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD) { 8019 temp1 |= 1U << 6; 8020 } 8021 if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD) { 8022 temp2 |= 1U << 6; 8023 } 8024 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD) { 8025 temp1 |= 1U << 5; 8026 } 8027 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD) { 8028 temp2 |= 1U << 5; 8029 } 8030 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD) { 8031 temp1 |= 1U << 4; 8032 } 8033 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD) { 8034 temp2 |= 1U << 4; 8035 } 8036 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD) { 8037 temp1 |= 1U << 3; 8038 } 8039 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD) { 8040 temp2 |= 1U << 3; 8041 } 8042 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD) { 8043 temp1 |= 1U << 2; 8044 } 8045 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD) { 8046 temp2 |= 1U << 2; 8047 } 8048 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD) { 8049 temp1 |= 1U << 1; 8050 } 8051 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD) { 8052 temp2 |= 1U << 1; 8053 } 8054 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD) { 8055 temp1 |= 1U << 0; 8056 } 8057 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD) { 8058 temp2 |= 1U << 0; 8059 } 8060 SOC_IF_ERROR_RETURN 8061 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc615, temp1)); 8062 8063 /* always load not supported at the moment */ 8064 /* 8065 SOC_IF_ERROR_RETURN 8066 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc615, temp2)); 8067 */ 8068 8069 break; 8070 8071 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT: 8072 temp1 = 0; 8073 8074 value0 = COMPILER_64_LO(value); 8075 8076 if (value0 & SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT) { 8077 temp1 |= 1U << 1; 8078 } 8079 if (value0 & SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT) { 8080 temp1 |= 1U << 0; 8081 } 8082 SOC_IF_ERROR_RETURN 8083 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc617, temp1)); 8084 break; 8085 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK: 8086 temp1 = 0; 8087 8088 value0 = COMPILER_64_LO(value); 8089 8090 if (value0 & SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT_MASK) { 8091 temp1 |= 1U << 1; 8092 } 8093 if (value0 & SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT_MASK) { 8094 temp1 |= 1U << 0; 8095 } 8096 SOC_IF_ERROR_RETURN 8097 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc616, temp1)); 8098 break; 8099 8100 case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET: 8101 value0 = COMPILER_64_LO(value); 8102 8103 SOC_IF_ERROR_RETURN 8104 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 8105 0xc60a, 8106 (uint16) (value0 & 0x0fff), 8107 0x0fff)); 8108 break; 8109 8110 case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET: 8111 value0 = COMPILER_64_LO(value); 8112 8113 SOC_IF_ERROR_RETURN 8114 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 8115 0xc60b, 8116 (uint16) (value0 & 0xffff))); 8117 SOC_IF_ERROR_RETURN 8118 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 8119 0xc60a, 8120 (uint16) ((value0 >> 4) & 0xf000), 0xf000)); 8121 break; 8122 default: 8123 return SOC_E_NONE; 8124 break; 8125 } 8126 8127 return SOC_E_NONE; 8128 } 8129 8130 int 8131 phy_84740_timesync_control_get(int unit, soc_port_t port, 8132 soc_port_control_phy_timesync_t type, 8133 uint64 *value) 8134 { 8135 uint16 value0 = 0; 8136 uint16 value1 = 0; 8137 uint16 value2 = 0; 8138 uint16 value3 = 0; 8139 uint32 value4 = 0; 8140 phy_ctrl_t *pc; 8141 8142 pc = EXT_PHY_SW_STATE(unit, port); 8143 8144 switch (type) { 8145 case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP: 8146 8147 SOC_IF_ERROR_RETURN 8148 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63d, 0x4)); 8149 8150 SOC_IF_ERROR_RETURN 8151 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc647, &value0)); 8152 SOC_IF_ERROR_RETURN 8153 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc646, &value1)); 8154 SOC_IF_ERROR_RETURN 8155 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc645, &value2)); 8156 8157 SOC_IF_ERROR_RETURN 8158 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63d, 0x8)); 8159 SOC_IF_ERROR_RETURN 8160 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63d, 0x0)); 8161 8162 /* *value = (((uint64)value3) << 48) | (((uint64)value2) << 32) | (((uint64)value1) << 16) | ((uint64)value0); */ 8163 COMPILER_64_SET((*value), 8164 (((uint32) value3 << 16) | ((uint32) value2)), 8165 (((uint32) value1 << 16) | ((uint32) value0))); 8166 break; 8167 case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP: 8168 8169 SOC_IF_ERROR_RETURN 8170 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63d, 0x1)); 8171 8172 SOC_IF_ERROR_RETURN 8173 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc640, &value0)); 8174 SOC_IF_ERROR_RETURN 8175 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63f, &value1)); 8176 SOC_IF_ERROR_RETURN 8177 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63e, &value2)); 8178 8179 SOC_IF_ERROR_RETURN 8180 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63d, 0x2)); 8181 SOC_IF_ERROR_RETURN 8182 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc63d, 0x0)); 8183 8184 /* *value = (((uint64)value3) << 48) | (((uint64)value2) << 32) | (((uint64)value1) << 16) | ((uint64)value0); */ 8185 COMPILER_64_SET((*value), 8186 (((uint32) value3 << 16) | ((uint32) value2)), 8187 (((uint32) value1 << 16) | ((uint32) value0))); 8188 break; 8189 8190 case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND: 8191 SOC_IF_ERROR_RETURN 8192 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc62f, &value0)); 8193 SOC_IF_ERROR_RETURN 8194 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc62e, &value1)); 8195 COMPILER_64_SET((*value), 0, 8196 (((uint32) value1 << 16) | ((uint32) value0))); 8197 break; 8198 8199 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME: 8200 SOC_IF_ERROR_RETURN 8201 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc632, &value0)); 8202 SOC_IF_ERROR_RETURN 8203 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc631, &value1)); 8204 SOC_IF_ERROR_RETURN 8205 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc630, &value2)); 8206 COMPILER_64_SET((*value), ((uint32) (value2 & 0x0fff)), 8207 (((uint32) value1 << 16) | ((uint32) value0))); 8208 COMPILER_64_SHL((*value), 4); 8209 break; 8210 8211 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL: 8212 8213 SOC_IF_ERROR_RETURN 8214 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc615, &value1)); 8215 /* always load not supported at the moment */ 8216 /* 8217 SOC_IF_ERROR_RETURN 8218 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc615, &value2)); 8219 */ 8220 value2 = 0; 8221 8222 value4 = 0; 8223 8224 if (value1 & (1U << 11)) { 8225 value4 |= SOC_PORT_PHY_TIMESYNC_TN_LOAD; 8226 } 8227 if (value2 & (1U << 11)) { 8228 value4 |= SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD; 8229 } 8230 if (value1 & (1U << 10)) { 8231 value4 |= SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD; 8232 } 8233 if (value2 & (1U << 10)) { 8234 value4 |= SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD; 8235 } 8236 if (value1 & (1U << 9)) { 8237 value4 |= SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD; 8238 } 8239 if (value2 & (1U << 9)) { 8240 value4 |= SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD; 8241 } 8242 if (value1 & (1U << 8)) { 8243 value4 |= SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD; 8244 } 8245 if (value1 & (1U << 8)) { 8246 value4 |= SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD; 8247 } 8248 if (value1 & (1U << 7)) { 8249 value4 |= SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD; 8250 } 8251 if (value1 & (1U << 7)) { 8252 value4 |= SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD; 8253 } 8254 if (value1 & (1U << 6)) { 8255 value4 |= SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD; 8256 } 8257 if (value2 & (1U << 6)) { 8258 value4 |= SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD; 8259 } 8260 if (value1 & (1U << 5)) { 8261 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD; 8262 } 8263 if (value2 & (1U << 5)) { 8264 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD; 8265 } 8266 if (value1 & (1U << 4)) { 8267 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD; 8268 } 8269 if (value2 & (1U << 4)) { 8270 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD; 8271 } 8272 if (value1 & (1U << 3)) { 8273 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD; 8274 } 8275 if (value2 & (1U << 3)) { 8276 value4 |= 8277 SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD; 8278 } 8279 if (value1 & (1U << 2)) { 8280 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD; 8281 } 8282 if (value2 & (1U << 2)) { 8283 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD; 8284 } 8285 if (value1 & (1U << 1)) { 8286 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD; 8287 } 8288 if (value2 & (1U << 1)) { 8289 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD; 8290 } 8291 if (value1 & (1U << 0)) { 8292 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD; 8293 } 8294 if (value2 & (1U << 0)) { 8295 value4 |= SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD; 8296 } 8297 COMPILER_64_SET((*value), 0, value4); 8298 8299 break; 8300 8301 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT: 8302 SOC_IF_ERROR_RETURN 8303 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc617, &value1)); 8304 8305 value0 = 0; 8306 8307 if (value1 & (1U << 1)) { 8308 value0 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT; 8309 } 8310 if (value1 & (1U << 0)) { 8311 value0 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT; 8312 } 8313 COMPILER_64_SET((*value), 0, (uint32) value0); 8314 8315 break; 8316 8317 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK: 8318 SOC_IF_ERROR_RETURN 8319 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc616, &value1)); 8320 value0 = 0; 8321 8322 if (value1 & (1U << 1)) { 8323 value0 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT_MASK; 8324 } 8325 if (value1 & (1U << 0)) { 8326 value0 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT_MASK; 8327 } 8328 COMPILER_64_SET((*value), 0, (uint32) value0); 8329 8330 break; 8331 8332 case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET: 8333 SOC_IF_ERROR_RETURN 8334 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc60a, &value0)); 8335 8336 COMPILER_64_SET((*value), 0, (uint32) (value0 & 0x0fff)); 8337 break; 8338 8339 case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET: 8340 SOC_IF_ERROR_RETURN 8341 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc60b, &value0)); 8342 8343 SOC_IF_ERROR_RETURN 8344 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc60a, &value1)); 8345 8346 COMPILER_64_SET((*value), 0, 8347 (uint32) (((((uint32) value1) << 4) & 0xf0000) | 8348 value0)); 8349 break; 8350 8351 default: 8352 return SOC_E_FAIL; 8353 } 8354 8355 return SOC_E_NONE; 8356 } 8357 8358 void 8359 _phy_84740_encode_egress_message_mode(soc_port_phy_timesync_event_message_egress_mode_t mode, 8360 int offset, uint16 *value) 8361 { 8362 8363 switch (mode) { 8364 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE: 8365 *value |= (0x0 << offset); 8366 break; 8367 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD: 8368 *value |= 8369 (0x1 << offset); 8370 break; 8371 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN: 8372 *value |= 8373 (0x2 << offset); 8374 break; 8375 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP: 8376 *value |= (0x3 << offset); 8377 break; 8378 } 8379 8380 } 8381 8382 void 8383 _phy_84740_encode_ingress_message_mode(soc_port_phy_timesync_event_message_ingress_mode_t mode, 8384 int offset, uint16 *value) 8385 { 8386 8387 switch (mode) { 8388 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE: 8389 *value |= (0x0 << offset); 8390 break; 8391 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD: 8392 *value |= 8393 (0x1 << offset); 8394 break; 8395 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP: 8396 *value |= (0x2 << offset); 8397 break; 8398 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME: 8399 *value |= (0x3 << offset); 8400 break; 8401 } 8402 8403 } 8404 8405 void _phy_84740_decode_egress_message_mode(uint16 value, int offset, 8406 soc_port_phy_timesync_event_message_egress_mode_t 8407 *mode) 8408 { 8409 8410 switch ((value >> offset) & 0x3) { 8411 case 0x0: 8412 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE; 8413 break; 8414 case 0x1: 8415 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD; 8416 break; 8417 case 0x2: 8418 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN; 8419 break; 8420 case 0x3: 8421 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP; 8422 break; 8423 } 8424 8425 } 8426 8427 void _phy_84740_decode_ingress_message_mode(uint16 value, int offset, 8428 soc_port_phy_timesync_event_message_ingress_mode_t 8429 *mode) 8430 { 8431 8432 switch ((value >> offset) & 0x3) { 8433 case 0x0: 8434 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE; 8435 break; 8436 case 0x1: 8437 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD; 8438 break; 8439 case 0x2: 8440 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP; 8441 break; 8442 case 0x3: 8443 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME; 8444 break; 8445 } 8446 8447 } 8448 8449 void _phy_84740_encode_gmode(soc_port_phy_timesync_global_mode_t mode, 8450 uint16 *value) 8451 { 8452 8453 switch (mode) { 8454 case SOC_PORT_PHY_TIMESYNC_MODE_FREE: 8455 *value = 0x1; 8456 break; 8457 case SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN: 8458 *value = 0x2; 8459 break; 8460 case SOC_PORT_PHY_TIMESYNC_MODE_CPU: 8461 *value = 0x3; 8462 break; 8463 default: 8464 break; 8465 } 8466 8467 } 8468 8469 void _phy_84740_decode_gmode(uint16 value, 8470 soc_port_phy_timesync_global_mode_t *mode) 8471 { 8472 8473 switch (value & 0x3) { 8474 case 0x1: 8475 *mode = SOC_PORT_PHY_TIMESYNC_MODE_FREE; 8476 break; 8477 case 0x2: 8478 *mode = SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN; 8479 break; 8480 case 0x3: 8481 *mode = SOC_PORT_PHY_TIMESYNC_MODE_CPU; 8482 break; 8483 default: 8484 break; 8485 } 8486 8487 } 8488 8489 void _phy_84740_encode_framesync_mode(soc_port_phy_timesync_framesync_mode_t 8490 mode, uint16 *value) 8491 { 8492 8493 switch (mode) { 8494 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0: 8495 *value = 1U << 0; 8496 break; 8497 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1: 8498 *value = 1U << 1; 8499 break; 8500 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT: 8501 *value = 1U << 2; 8502 break; 8503 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU: 8504 *value = 1U << 3; 8505 break; 8506 default: 8507 break; 8508 } 8509 8510 } 8511 8512 void _phy_84740_decode_framesync_mode(uint16 value, 8513 soc_port_phy_timesync_framesync_mode_t *mode) 8514 { 8515 8516 switch (value & 0xf) { 8517 case 1U << 0: 8518 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0; 8519 break; 8520 case 1U << 1: 8521 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1; 8522 break; 8523 case 1U << 2: 8524 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT; 8525 break; 8526 case 1U << 3: 8527 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU; 8528 break; 8529 default: 8530 break; 8531 } 8532 8533 } 8534 8535 void _phy_84740_encode_syncout_mode(soc_port_phy_timesync_syncout_mode_t mode, 8536 uint16 *value) 8537 { 8538 8539 switch (mode) { 8540 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE: 8541 *value = 0x0; 8542 break; 8543 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME: 8544 *value = 0x1; 8545 break; 8546 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN: 8547 *value = 0x2; 8548 break; 8549 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC: 8550 *value = 0x3; 8551 break; 8552 } 8553 8554 } 8555 8556 void _phy_84740_decode_syncout_mode(uint16 value, 8557 soc_port_phy_timesync_syncout_mode_t *mode) 8558 { 8559 8560 switch (value & 0x3) { 8561 case 0x0: 8562 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE; 8563 break; 8564 case 0x1: 8565 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME; 8566 break; 8567 case 0x2: 8568 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN; 8569 break; 8570 case 0x3: 8571 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC; 8572 break; 8573 } 8574 8575 } 8576 8577 /* 8578 * Variable: 8579 * phy_84740_drv 8580 * Purpose: 8581 * Phy Driver for 40G PHY. 8582 */ 8583 8584 phy_driver_t phy_84740drv_xe = { 8585 "84740 10-Gigabit PHY Driver", 8586 phy_84740_init, /* Init */ 8587 phy_null_reset, /* Reset (dummy) */ 8588 phy_84740_link_get, /* Link get */ 8589 phy_84740_enable_set, /* Enable set */ 8590 phy_null_enable_get, /* Enable get */ 8591 phy_null_set, /* Duplex set */ 8592 phy_null_one_get, /* Duplex get */ 8593 phy_84740_speed_set, /* Speed set */ 8594 phy_84740_speed_get, /* Speed get */ 8595 phy_null_set, /* Master set */ 8596 phy_null_zero_get, /* Master get */ 8597 phy_84740_an_set, /* ANA set */ 8598 phy_84740_an_get, /* ANA get */ 8599 NULL, /* Local Advert set */ 8600 NULL, /* Local Advert get */ 8601 phy_null_mode_get, /* Remote Advert get */ 8602 phy_84740_lb_set, /* PHY loopback set */ 8603 phy_84740_lb_get, /* PHY loopback set */ 8604 phy_84740_interface_set, /* IO Interface set */ 8605 phy_84740_interface_get, /* IO Interface get */ 8606 NULL, /* PHY abilities mask */ 8607 NULL, 8608 NULL, 8609 phy_null_mdix_set, 8610 phy_null_mdix_get, 8611 phy_null_mdix_status_get, 8612 NULL, 8613 NULL, 8614 phy_null_medium_get, 8615 NULL, /* phy_cable_diag */ 8616 NULL, /* phy_link_change */ 8617 phy_84740_control_set, /* phy_control_set */ 8618 phy_84740_control_get, /* phy_control_get */ 8619 phy_84740_reg_read, /* phy_reg_read */ 8620 phy_84740_reg_write, /* phy_reg_write */ 8621 NULL, /* phy_reg_modify */ 8622 NULL, /* phy_notify */ 8623 phy_84740_probe, /* pd_probe */ 8624 phy_84740_ability_advert_set, /* pd_ability_advert_set */ 8625 phy_84740_ability_advert_get, /* pd_ability_advert_get */ 8626 phy_84740_ability_remote_get, /* pd_ability_remote_get */ 8627 phy_84740_ability_local_get, /* pd_ability_local_get */ 8628 phy_84740_firmware_set, /* pd_firmware_set */ 8629 phy_84740_timesync_config_set, /* pd_timesync_config_set */ 8630 phy_84740_timesync_config_get, /* pd_timesync_config_get */ 8631 phy_84740_timesync_control_set, /* pd_timesync_control_set */ 8632 phy_84740_timesync_control_get, /* pd_timesync_control_get */ 8633 phy_84740_diag_ctrl, /* pd_diag_ctrl */ 8634 NULL, /* pd_lane_control_set */ 8635 NULL, /* pd_lane_control_get */ 8636 NULL, /* pd_lane_reg_read */ 8637 NULL, /* pd_lane_reg_write */ 8638 NULL, /* pd_oam_config_set */ 8639 NULL, /* pd_oam_config_get */ 8640 NULL, /* pd_oam_control_set */ 8641 NULL, /* pd_oam_control_get */ 8642 NULL, /* pd_timesync_enhanced_capture_get */ 8643 phy_84740_multi_get, /* pd_multi_get */ 8644 phy_84740_precondition_before_probe /* pd_precondition_before_probe */ 8645 }; 8646 8647 #else /* INCLUDE_PHY_84740 */ 8648 int _phy_84740_not_empty; 8649 #endif /* INCLUDE_PHY_84740 */