phy84728.c (201663B)
1 /* 2 * 3 * 4 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 5 * 6 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 7 * 8 * File: phy84728.c 9 * Purpose: SDK PHY driver for BCM84728 10 * 11 * Supported BCM84XXX Family of PHY devices: 12 * 13 * Device Ports Media MAC Interface 14 * 84707 1 1 10G SFP+ XAUI 15 * 84073 2 2 KR XAUI 16 * 84074 4 4 KR XAUI 17 * 84728 2 2 10G SFP+/WAN XAUI 18 * 84748 4 4 10G SFP+/WAN XAUI 19 * 84727/84722 2 2 10G SFP+ XAUI 20 * 84747/84742 4 4 10G SFP+ XAUI 21 * 84762 2 2 10G SFP+ RXAUI 22 * 84764 4 4 10G SFP+ RXAUI 23 * 84042 2 2 KR RXAUI 24 * 84044 4 4 KR RXAUI 25 * 26 * Workarounds: 27 * 28 * References: 29 * 30 * Notes: 31 */ 32 33 34 #include <sal/types.h> 35 #include <sal/core/spl.h> 36 #include <shared/bsl.h> 37 #include <soc/drv.h> 38 #include <soc/debug.h> 39 #include <soc/error.h> 40 #include <soc/phyreg.h> 41 42 #include <soc/phy.h> 43 #include <soc/phy/phyctrl.h> 44 #include <soc/phy/drv.h> 45 46 #include "phydefs.h" /* Must include before other phy related includes */ 47 48 49 50 #if defined(INCLUDE_PHY_84728) 51 #include "phyconfig.h" /* Must be the first phy include after phydefs.h */ 52 #include "phyident.h" 53 #include "phyreg.h" 54 #include "phynull.h" 55 #include "phyfege.h" 56 #include "phyxehg.h" 57 58 #include "phy84728_int.h" 59 #include "phy84728.h" 60 61 #define LAN_MODE 0 62 #define WAN_MODE 1 63 STATIC int 64 _phy_84728_mode_set(int unit, soc_port_t port, uint32 mode); 65 66 67 #define ADVERT_ALL_COPPER \ 68 (SOC_PA_PAUSE | SOC_PA_SPEED_10MB | \ 69 SOC_PA_SPEED_100MB | SOC_PA_SPEED_1000MB) 70 71 #define ADVERT_ALL_FIBER \ 72 (SOC_PA_PAUSE | SOC_PA_SPEED_1000MB) 73 74 #define ADVERT_ALL_10GFIBER \ 75 (SOC_PA_PAUSE | SOC_PA_SPEED_10GB) 76 77 #define WRITE_PHY84728_PMA_PMD_REG(_unit, _phy_ctrl, _reg,_val) \ 78 WRITE_PHY_REG((_unit), (_phy_ctrl), \ 79 SOC_PHY_CLAUSE45_ADDR(1, (_reg)), (_val)) 80 81 #define MODIFY_PHY84728_PMA_PMD_REG(_unit, _phy_ctrl, _reg, _val, _mask) \ 82 MODIFY_PHY_REG((_unit), (_phy_ctrl), \ 83 SOC_PHY_CLAUSE45_ADDR(1, (_reg)), (_val), (_mask)) 84 85 86 #define PHY84728_REG_READ(_unit, _phy_ctrl, _addr, _val) \ 87 READ_PHY_REG((_unit), (_phy_ctrl), (_addr), (_val)) 88 89 #define READ_PHY84728_PMA_PMD_REG(_unit, _phy_ctrl, _reg,_val) \ 90 PHY84728_REG_READ((_unit), (_phy_ctrl), \ 91 SOC_PHY_CLAUSE45_ADDR(1, (_reg)), (_val)) 92 93 #define NXT_PC(pc) ((phy_ctrl_t *)((pc)->driver_data)) 94 #define PHYDRV_CALL_NOARG(pc,name) \ 95 do { \ 96 if (pc->driver_data) { \ 97 int rv; \ 98 phy_ctrl_t * tmp_pc = EXT_PHY_SW_STATE(pc->unit, pc->port); \ 99 EXT_PHY_SW_STATE(pc->unit,pc->port) = (phy_ctrl_t *)(pc->driver_data); \ 100 rv = name(((phy_ctrl_t *)(pc->driver_data))->pd,(pc)->unit,(pc)->port); \ 101 EXT_PHY_SW_STATE(pc->unit, pc->port) = tmp_pc; \ 102 if (SOC_FAILURE(rv)) { \ 103 return rv; \ 104 } \ 105 } \ 106 } while(0) 107 108 #define PHYDRV_CALL_ARG1(pc,name,arg0) \ 109 do { \ 110 if (pc->driver_data) { \ 111 int rv; \ 112 phy_ctrl_t * tmp_pc = EXT_PHY_SW_STATE(pc->unit, pc->port); \ 113 EXT_PHY_SW_STATE(pc->unit, pc->port) = (phy_ctrl_t *)(pc->driver_data); \ 114 rv = name(((phy_ctrl_t *)(pc->driver_data))->pd,(pc)->unit, \ 115 (pc)->port,arg0); \ 116 EXT_PHY_SW_STATE(pc->unit, pc->port) = tmp_pc; \ 117 if (SOC_FAILURE(rv)) { \ 118 return rv; \ 119 } \ 120 } \ 121 } while(0) 122 123 #define PHYDRV_CALL_ARG2(pc,name,arg0,arg1) \ 124 do { \ 125 if (pc->driver_data) { \ 126 int rv; \ 127 phy_ctrl_t * tmp_pc = EXT_PHY_SW_STATE(pc->unit, pc->port); \ 128 EXT_PHY_SW_STATE(pc->unit, pc->port) = (phy_ctrl_t *)(pc->driver_data); \ 129 rv=name(((phy_ctrl_t *)(pc->driver_data))->pd,(pc)->unit,(pc)->port,arg0, \ 130 arg1); \ 131 EXT_PHY_SW_STATE(pc->unit, pc->port) = tmp_pc; \ 132 if (SOC_FAILURE(rv)) { \ 133 return rv; \ 134 } \ 135 } \ 136 } while(0) 137 138 #define PHYDRV_CALL_ARG3(pc,name,arg0,arg1,arg2) \ 139 do { \ 140 if (pc->driver_data) { \ 141 int rv; \ 142 phy_ctrl_t * tmp_pc = EXT_PHY_SW_STATE(pc->unit, pc->port); \ 143 EXT_PHY_SW_STATE(pc->unit, pc->port) = (phy_ctrl_t *)(pc->driver_data); \ 144 rv=name(((phy_ctrl_t *)(pc->driver_data))->pd,(pc)->unit,(pc)->port,arg0, \ 145 arg1,arg2); \ 146 EXT_PHY_SW_STATE(pc->unit, pc->port) = tmp_pc; \ 147 if (SOC_FAILURE(rv)) { \ 148 return rv; \ 149 } \ 150 } \ 151 } while(0) 152 153 #define BSDK_PHY84728_LINE_MAC_PORT(p) (p) 154 #define BSDK_PHY84728_SWITCH_MAC_PORT(p) ((p) + 1) 155 #define PHY84728_PDET_MASK (1 << 0) 156 157 /* 158 * PHY Map structure for mapping mac drivers 159 */ 160 typedef struct phy84728_map_s { 161 bsdk_phy84728_intf_t line_mode; /* configured line mode */ 162 uint32 phy_sys_xaui_tx_lane_map; 163 uint32 phy_sys_xaui_rx_lane_map; 164 uint32 devid; 165 uint32 reverse_mode; 166 uint32 link_down; 167 168 }phy84728_map_t; 169 170 #define PHY84728_MAP(_pc) ((phy84728_map_t *)((_pc) + 1)) 171 #define REVERSE_MODE(_pc) ((PHY84728_MAP(_pc))->reverse_mode) 172 173 #define BSDK_PHY84728_IS_KR_VARIANT(devid) \ 174 ( (devid) == 0x84073 ||\ 175 (devid) == 0x84074 ||\ 176 (devid) == 0x84042 ||\ 177 (devid) == 0x84044 ) 178 179 #define BSDK_PHY84728_IS_84728(devid) \ 180 ( (devid) == 0x84728 ) 181 182 #define PHY_84727_EDC_MODE_MASK 0xff 183 184 /* OUI from ID0 and ID1 registers contents */ 185 #define BSDK_PHY84728_PHY_OUI(id0, id1) \ 186 bsdk_phy84728_bit_rev_by_byte_word32((uint32)(id0) << 6 | \ 187 ((id1) >> 10 & 0x3f)) 188 189 /* PHY model from ID0 and ID1 register Contents */ 190 #define BSDK_PHY84728_PHY_MODEL(id0, id1) ((id1) >> 4 & 0x3f) 191 192 /* PHY revision from ID0 and ID1 register Contents */ 193 #define BSDK_PHY84728_PHY_REV(id0, id1) ((id1) & 0xf) 194 195 /* 196 * Function: 197 * bsdk_bit_rev_by_byte_word32 198 * Purpose: 199 * Reverse the bits in each byte of a 32 bit long 200 * Parameters: 201 * n - 32bit input 202 * Notes: 203 */ 204 STATIC uint32 205 bsdk_phy84728_bit_rev_by_byte_word32(uint32 n) 206 { 207 n = (((n & 0xaaaaaaaa) >> 1) | ((n & 0x55555555) << 1)); 208 n = (((n & 0xcccccccc) >> 2) | ((n & 0x33333333) << 2)); 209 n = (((n & 0xf0f0f0f0) >> 4) | ((n & 0x0f0f0f0f) << 4)); 210 return n; 211 } 212 213 STATIC int phy_84728_init(int unit, soc_port_t port); 214 STATIC int phy_84728_link_get(int unit, soc_port_t port, int *link); 215 STATIC int phy_84728_enable_set(int unit, soc_port_t port, int enable); 216 STATIC int phy_84728_duplex_set(int unit, soc_port_t port, int duplex); 217 STATIC int phy_84728_duplex_get(int unit, soc_port_t port, int *duplex); 218 STATIC int phy_84728_speed_set(int unit, soc_port_t port, int speed); 219 STATIC int phy_84728_speed_get(int unit, soc_port_t port, int *speed); 220 STATIC int phy_84728_master_set(int unit, soc_port_t port, int master); 221 STATIC int phy_84728_master_get(int unit, soc_port_t port, int *master); 222 STATIC int phy_84728_an_set(int unit, soc_port_t port, int autoneg); 223 STATIC int phy_84728_an_get(int unit, soc_port_t port, 224 int *autoneg, int *autoneg_done); 225 STATIC int phy_84728_lb_set(int unit, soc_port_t port, int enable); 226 STATIC int phy_84728_lb_get(int unit, soc_port_t port, int *enable); 227 STATIC int phy_84728_medium_config_set(int unit, soc_port_t port, 228 soc_port_medium_t medium, 229 soc_phy_config_t *cfg); 230 STATIC int phy_84728_medium_config_get(int unit, soc_port_t port, 231 soc_port_medium_t medium, 232 soc_phy_config_t *cfg); 233 STATIC int phy_84728_ability_advert_set(int unit, soc_port_t port, 234 soc_port_ability_t *ability); 235 STATIC int phy_84728_ability_advert_get(int unit, soc_port_t port, 236 soc_port_ability_t *ability); 237 STATIC int phy_84728_ability_remote_get(int unit, soc_port_t port, 238 soc_port_ability_t *ability); 239 STATIC int phy_84728_ability_local_get(int unit, soc_port_t port, 240 soc_port_ability_t *ability); 241 STATIC int phy_84728_firmware_set(int unit, int port, int offset, 242 uint8 *data, int len); 243 STATIC int phy_84728_control_set(int unit, soc_port_t port, 244 soc_phy_control_t type, uint32 value); 245 STATIC int phy_84728_control_get(int unit, soc_port_t port, 246 soc_phy_control_t type, uint32 *value); 247 STATIC int phy_84728_link_up(int unit, soc_port_t port); 248 STATIC int bsdk_phy84728_line_mode_set(phy_ctrl_t *pc, int dev_port, 249 bsdk_phy84728_intf_t mode); 250 STATIC int bsdk_phy84728_sys_mode_set(phy_ctrl_t *pc, int dev_port, 251 bsdk_phy84728_intf_t mode); 252 253 STATIC int 254 _bsdk_phy84728_system_sgmii_duplex_set(phy_ctrl_t *pc, int dev_port, int duplex); 255 STATIC int 256 _bsdk_phy84728_system_sgmii_sync(phy_ctrl_t *pc, int dev_port); 257 258 extern uint8 bcm84728_fw[]; 259 extern uint32 bcm84728_fw_length; 260 extern uint8 bcm84748_fw[]; 261 extern uint32 bcm84748_fw_length; 262 263 #define NEW_NAME_ARRAY_SIZE 25 264 STATIC int 265 _phy_84728_nxt_dev_probe(int unit, soc_port_t port) 266 { 267 phy_ctrl_t *pc; 268 phy_ctrl_t phy_ctrl; 269 soc_phy_info_t phy_info; 270 extern int _ext_phy_probe(int unit, soc_port_t port,soc_phy_info_t *pi, 271 phy_ctrl_t *ext_pc); 272 soc_phy_info_t *pi; 273 int offset = 0; 274 char new_name[NEW_NAME_ARRAY_SIZE]; 275 276 pc = EXT_PHY_SW_STATE(unit, port); 277 278 /* initialize the phy_ctrl for the next device connected to the XFI port */ 279 sal_memset(&phy_ctrl, 0, sizeof(phy_ctrl_t)); 280 phy_ctrl.unit = unit; 281 phy_ctrl.port = port; 282 phy_ctrl.speed_max = pc->speed_max; 283 phy_ctrl.read = pc->read; /* use same MDIO read routine as this device's */ 284 phy_ctrl.write = pc->write; /* use same MDIO write routine as this device's */ 285 286 /* get the mdio address of the next device */ 287 phy_ctrl.phy_id = soc_property_port_get(unit, port, 288 spn_PORT_PHY_ADDR1, 0xff); 289 290 if (phy_ctrl.phy_id == 0xff) { 291 return SOC_E_NOT_FOUND; 292 } 293 294 /* probe the next device at the given address */ 295 SOC_IF_ERROR_RETURN 296 (_ext_phy_probe(unit, port, &phy_info, &phy_ctrl)); 297 298 /* If we have probed 84728/84764 then we won't allow 299 * to chain (physically its not possible) another of the same type. 300 * The Probe depends on spn_PORT_PHY_ADDR1 to probe 2nd level PHYs. 301 * It could so happen that 84728/84764 could be chained with 8481. 302 * In such cases probing could end up in a loop. 303 */ 304 if ((phy_ctrl.pd == NULL) || ((phy_ctrl.phy_model == pc->phy_model) && 305 (phy_ctrl.phy_oui == pc->phy_oui))) { 306 pc->driver_data = NULL; 307 /* device not found */ 308 return SOC_E_NOT_FOUND; 309 } 310 311 LOG_INFO(BSL_LS_SOC_PHY, 312 (BSL_META_U(unit, 313 "_phy_84728_nxt_dev_probe: found phy device" 314 " u=%d p=%d id0=0x%x id1=0x%x\n"), 315 unit, port,phy_ctrl.phy_id0,phy_ctrl.phy_id1)); 316 317 /* set the chained flag */ 318 PHY_FLAGS_SET(phy_ctrl.unit, phy_ctrl.port, PHY_FLAGS_CHAINED); 319 320 /* Found device, allocate control structure */ 321 pc->driver_data = (void *)sal_alloc (sizeof (phy_ctrl_t) + phy_ctrl.size, phy_ctrl.pd->drv_name); 322 if (pc->driver_data == NULL) { 323 return SOC_E_MEMORY; 324 } 325 sal_memcpy(pc->driver_data, &phy_ctrl, sizeof(phy_ctrl_t)); 326 327 /* We need to append the (chanined) PHY's name to the parent */ 328 pi = &SOC_PHY_INFO(unit, pc->port); 329 offset = sal_strlen(pi->phy_name); 330 /* size of new_name is 25 which is large enough */ 331 /* coverity[secure_coding] */ 332 sal_strcpy(new_name, (pi->phy_name)); 333 /* coverity[secure_coding] */ 334 sal_strcpy(new_name+offset, "->"); 335 offset = sal_strlen(new_name); 336 if ((offset + sal_strlen(phy_info.phy_name)) < NEW_NAME_ARRAY_SIZE) { 337 /* coverity[secure_coding] */ 338 sal_strcpy(new_name + offset, phy_info.phy_name); 339 } else { 340 return SOC_E_MEMORY; 341 } 342 pi->phy_name = sal_strdup(new_name); 343 344 return SOC_E_NONE; 345 } 346 #if defined(NEW_NAME_ARRAY_SIZE) 347 #undef NEW_NAME_ARRAY_SIZE 348 #endif 349 350 351 /* 352 * Function: 353 * _phy_84728_medium_config_update 354 * Purpose: 355 * Update the PHY with config parameters 356 * Parameters: 357 * unit - StrataSwitch unit #. 358 * port - StrataSwitch port #. 359 * cfg - Config structure. 360 * Returns: 361 * SOC_E_XXX 362 */ 363 364 STATIC int 365 _phy_84728_medium_config_update(int unit, soc_port_t port, 366 soc_phy_config_t *cfg) 367 { 368 369 SOC_IF_ERROR_RETURN 370 (phy_84728_speed_set(unit, port, cfg->force_speed)); 371 SOC_IF_ERROR_RETURN 372 (phy_84728_duplex_set(unit, port, cfg->force_duplex)); 373 SOC_IF_ERROR_RETURN 374 (phy_84728_ability_advert_set(unit, port, &cfg->advert_ability)); 375 SOC_IF_ERROR_RETURN 376 (phy_84728_an_set(unit, port, cfg->autoneg_enable)); 377 378 return SOC_E_NONE; 379 } 380 381 /* 382 * Squelch enable/disable 383 * 1) 10G XAUI output squelching enable: 1.C842.12=1 AND 1.C842.11=0; 384 * 2) 1G XAUI output squelching enable: 1.C842.10=1 385 */ 386 STATIC int 387 _phy_84728_squelch_enable(int unit, soc_port_t port, int enable) 388 { 389 phy_ctrl_t *pc; 390 uint16 data16, mask16; 391 int speed; 392 393 pc = EXT_PHY_SW_STATE(unit, port); 394 395 if (REVERSE_MODE(pc)) { 396 /* not squelch support in reverse mode - do nothing */ 397 return SOC_E_NONE; 398 } 399 400 SOC_IF_ERROR_RETURN 401 (phy_84728_speed_get(unit, port, &speed)); 402 403 if (speed == 10000) { 404 mask16 = (1<<12); 405 data16 = enable ? mask16 : 0; 406 mask16 = ((1<<12) | (1<<11)); 407 SOC_IF_ERROR_RETURN 408 (MODIFY_PHY84728_PMA_PMD_REG(unit, pc, 0xC842, data16, mask16)); 409 } else { 410 mask16 = (1<<10); 411 data16 = enable ? mask16 : 0; 412 SOC_IF_ERROR_RETURN 413 (MODIFY_PHY84728_PMA_PMD_REG(unit, pc, 0xC842, data16, mask16)); 414 } 415 416 return SOC_E_NONE; 417 } 418 419 /* Function: 420 * phy_84728_init 421 * Purpose: 422 * Initialize 84728 phys 423 * Parameters: 424 * unit - StrataSwitch unit #. 425 * port - StrataSwitch port #. 426 * Returns: 427 * SOC_E_NONE 428 */ 429 430 STATIC int 431 phy_84728_init(int unit, soc_port_t port) 432 { 433 int wan_mode; 434 phy_ctrl_t *pc; 435 int line_mode; 436 int fiber_preferred; 437 int phy_ext_rom_boot; 438 int rv; 439 char *str; 440 /* 441 _phy84728_event_callback_data_t *tmp; 442 */ 443 /*uint16 ctrl, tmp2;*/ 444 uint16 temp; 445 uint16 devid; 446 uint16 mask16; 447 uint16 data16; 448 phy_ctrl_t *int_pc; 449 450 pc = EXT_PHY_SW_STATE(unit, port); 451 452 sal_memset(PHY84728_MAP(pc), 0, sizeof(phy84728_map_t)); 453 454 PHY84728_MAP(pc)->link_down = 1; 455 456 if (READ_PHY84728_PMA_PMD_REG(unit, pc, 0xc802, &devid) < 0) { 457 return SOC_E_FAIL; 458 } 459 460 PHY84728_MAP(pc)->devid = devid; 461 462 if (READ_PHY84728_PMA_PMD_REG(unit, pc, 0xc803, &devid) < 0) { 463 return SOC_E_FAIL; 464 } 465 466 PHY84728_MAP(pc)->devid |= ((devid & 0xf) << 16) ; 467 468 if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) { 469 phy_ext_rom_boot = soc_property_port_get(unit, port, 470 spn_PHY_EXT_ROM_BOOT, 1); 471 if (!phy_ext_rom_boot) { 472 pc->flags |= PHYCTRL_MDIO_BCST; 473 pc->dev_name = "BCM84728"; 474 } 475 /* indicate second pass of init is needed */ 476 PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS2); 477 return SOC_E_NONE; 478 } 479 480 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) || 481 (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) { 482 483 LOG_INFO(BSL_LS_SOC_PHY, 484 (BSL_META_U(unit, 485 "phy_84728_init: u=%d p=%d\n"),unit, port)); 486 487 REVERSE_MODE(pc) = soc_property_port_suffix_num_get(unit, port, 84728, 488 spn_PORT_PHY_MODE_REVERSE, "phy", 0); 489 490 491 /* Preferred mode: 492 * phy_fiber_pref = 1 ; Port is in SFI mode in 10G Default 493 * when speed is changed to 1G, its 1000X 494 * phy_fiber_pref = 0; Port is in SGMII mode, allows only 1G/100M/10M 495 */ 496 fiber_preferred = 497 soc_property_port_get(unit, port, spn_PHY_FIBER_PREF, 1); 498 499 /* Initially configure for the preferred medium. */ 500 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER); 501 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 502 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_PASSTHRU); 503 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX); 504 505 if (fiber_preferred) { 506 line_mode = BSDK_PHY84728_INTF_SFI; 507 pc->copper.enable = FALSE; 508 pc->fiber.enable = TRUE; 509 pc->interface = SOC_PORT_IF_XFI; 510 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 511 } else { 512 pc->interface = SOC_PORT_IF_SGMII; 513 line_mode = BSDK_PHY84728_INTF_SGMII; 514 pc->copper.enable = TRUE; 515 pc->fiber.enable = FALSE; 516 PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER); 517 } 518 PHY_FLAGS_SET(unit, port, PHY_FLAGS_C45); 519 520 pc->copper.preferred = !fiber_preferred; 521 pc->copper.autoneg_enable = TRUE; 522 pc->copper.autoneg_advert = ADVERT_ALL_COPPER; 523 pc->copper.force_speed = 1000; 524 pc->copper.force_duplex = TRUE; 525 pc->copper.master = SOC_PORT_MS_AUTO; 526 pc->copper.mdix = SOC_PORT_MDIX_AUTO; 527 528 pc->fiber.preferred = TRUE; 529 pc->fiber.autoneg_enable = FALSE; 530 pc->fiber.autoneg_advert = ADVERT_ALL_FIBER; 531 pc->fiber.force_speed = 10000; 532 pc->fiber.force_duplex = TRUE; 533 pc->fiber.master = SOC_PORT_MS_NONE; 534 pc->fiber.mdix = SOC_PORT_MDIX_NORMAL; 535 536 /* config DAC mode and backplane mode for KR/LR4/SR4 */ 537 mask16 = BSDK_PHY84728_LN_DEV1_CHIP_MODE_DAC_MASK | 538 BSDK_PHY84728_LN_DEV1_CHIP_MODE_BKPLANE_MASK ; 539 if (BSDK_PHY84728_IS_KR_VARIANT(PHY84728_MAP(pc)->devid)) { 540 data16 = BSDK_PHY84728_LN_DEV1_CHIP_MODE_BKPLANE_MASK; 541 } else { 542 data16 = 0; 543 } 544 545 SOC_IF_ERROR_RETURN( 546 BSDK_MOD_PHY84728_LN_DEV1_CHIP_MODEr(pc, data16, mask16)); 547 548 549 SOC_IF_ERROR_RETURN( 550 bsdk_phy84728_reset(pc)); 551 552 /* Check where to load ucode from again in pass2 */ 553 phy_ext_rom_boot = soc_property_port_get(unit, port, 554 spn_PHY_EXT_ROM_BOOT, 1); 555 SOC_IF_ERROR_RETURN( 556 bsdk_phy84728_no_reset_setup(pc, 557 line_mode, 558 phy_ext_rom_boot)); 559 560 /* Get Requested LED selectors (defaults are hardware defaults) */ 561 pc->ledmode[0] = soc_property_port_get(unit, port, spn_PHY_LED1_MODE, 0); 562 pc->ledmode[1] = soc_property_port_get(unit, port, spn_PHY_LED2_MODE, 1); 563 pc->ledmode[2] = soc_property_port_get(unit, port, spn_PHY_LED3_MODE, 3); 564 pc->ledmode[3] = soc_property_port_get(unit, port, spn_PHY_LED4_MODE, 6); 565 pc->ledctrl = soc_property_port_get(unit, port, spn_PHY_LED_CTRL, 0x8); 566 pc->ledselect = soc_property_port_get(unit, port, spn_PHY_LED_SELECT, 0); 567 568 /* WAN/LAN mode set */ 569 wan_mode = soc_property_port_get(unit, port, spn_PHY_WAN_MODE, FALSE); 570 571 if (wan_mode) { 572 SOC_IF_ERROR_RETURN 573 (_phy_84728_mode_set(unit, port, WAN_MODE)); 574 } else { 575 SOC_IF_ERROR_RETURN 576 (_phy_84728_mode_set(unit, port, LAN_MODE)); 577 } 578 579 LOG_INFO(BSL_LS_SOC_PHY, 580 (BSL_META_U(unit, 581 "84728: u=%d port=%d mode=%s : init.\n"), 582 unit, port, wan_mode ? "WAN" : "LAN")); 583 584 585 /* XAUI RX Lane Swap (Lane A, B, C, D changes to Lane D, C, B, A) */ 586 str = soc_property_port_get_str(unit, port, spn_PHY_XAUI_RX_LANE_SWAP); 587 if (str != NULL) { 588 temp = soc_property_port_get(unit, port, 589 spn_PHY_XAUI_RX_LANE_SWAP, 0); 590 } else { 591 temp = 0; 592 } 593 PHY84728_MAP(pc)->phy_sys_xaui_rx_lane_map = (temp) ? 0x3210 : 0; 594 595 596 /* XAUI TX Lane Swap (Lane A, B, C, D changes to Lane D, C, B, A) */ 597 str = soc_property_port_get_str(unit, port, spn_PHY_XAUI_TX_LANE_SWAP); 598 if (str != NULL) { 599 temp = soc_property_port_get(unit, port, 600 spn_PHY_XAUI_TX_LANE_SWAP, 0); 601 } else { 602 temp = 0; 603 } 604 PHY84728_MAP(pc)->phy_sys_xaui_tx_lane_map = (temp) ? 0x3210 : 0; 605 606 607 #if 0 608 /* Use lane mapping */ 609 SOC_IF_ERROR_RETURN( 610 bsdk_phy84728_lane_map(pc)); 611 #endif 612 613 614 if (line_mode != BSDK_PHY84728_INTF_SGMII) { 615 SOC_IF_ERROR_RETURN 616 (_phy_84728_medium_config_update(unit, port, &pc->fiber)); 617 } 618 619 int_pc = INT_PHY_SW_STATE(unit, port); 620 if (NULL != int_pc) { 621 PHY_AUTO_NEGOTIATE_SET (int_pc->pd, unit, port, 0); 622 PHY_SPEED_SET(int_pc->pd, unit, port, 10000); 623 } 624 625 if (IS_HG_PORT(unit, port)) { 626 SOC_IF_ERROR_RETURN( 627 BSDK_PHY84728_REG_WR(pc, 0x00, 0x0004, 0x8007, 0x0040)); 628 SOC_IF_ERROR_RETURN( 629 BSDK_PHY84728_REG_MOD(pc, 0x00, 0x0001, 0xcd08, 0x0100, 0x0100)); 630 } 631 632 /* Enable Squelch */ 633 SOC_IF_ERROR_RETURN(_phy_84728_squelch_enable(unit, port, TRUE)); 634 635 rv = _phy_84728_nxt_dev_probe(unit,port); 636 if (SOC_SUCCESS(rv)) { 637 PHYDRV_CALL_NOARG(pc,PHY_INIT); 638 } 639 } 640 return SOC_E_NONE; 641 } 642 643 STATIC int 644 _phy_54942_link_get(int unit, soc_port_t port, int *link) 645 { 646 phy_ctrl_t *pc; 647 uint16 xgxsstatus1, status1000x1; 648 649 pc = EXT_PHY_SW_STATE(unit, port); 650 651 SOC_IF_ERROR_RETURN 652 (BSDK_RD_PHY84728_SYS_DEV4_XGXSSTATUS1r(pc, &xgxsstatus1)); 653 654 SOC_IF_ERROR_RETURN 655 (BSDK_RD_PHY84728_SYS_DEV4_XGXS_BASE1000X_STAT1r(pc, &status1000x1)); 656 657 if (xgxsstatus1 == 0xffff) { 658 *link = 0 ; 659 } else { 660 *link = ((xgxsstatus1 & (1U << 2)) | (status1000x1 & (1U << 1))) ? 1 : 0; 661 } 662 663 LOG_VERBOSE(BSL_LS_SOC_PHY, 664 (BSL_META_U(unit, 665 "_phy_54942_link_get: u=%d port%d: link:%s\n"), 666 unit, port, *link ? "Up": "Down")); 667 668 return SOC_E_NONE; 669 } 670 671 672 /* 673 * Function: 674 * phy_84728_link_get 675 * Purpose: 676 * Get layer2 connection status. 677 * Parameters: 678 * unit - StrataSwitch unit #. 679 * port - StrataSwitch port #. 680 * link - address of memory to store link up/down state. 681 * Returns: 682 * SOC_E_NONE 683 */ 684 685 STATIC int 686 phy_84728_link_get(int unit, soc_port_t port, int *link) 687 { 688 phy_ctrl_t *pc; 689 int rv = SOC_E_NONE; 690 bsdk_phy84728_intf_t bsdk_mode; 691 int bsdk_link; 692 uint16 wis_mii_stat; 693 694 pc = EXT_PHY_SW_STATE(unit, port); 695 *link = FALSE; /* Default return */ 696 697 698 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 699 return SOC_E_NONE; 700 } 701 702 if (NXT_PC(pc)) { 703 PHYDRV_CALL_ARG1(pc, PHY_LINK_GET, link); 704 return SOC_E_NONE; 705 } 706 707 rv = bsdk_phy84728_line_intf_get(pc, 0, &bsdk_mode); 708 if (!SOC_SUCCESS(rv)) { 709 return SOC_E_FAIL; 710 } 711 712 if ((bsdk_mode == BSDK_PHY84728_INTF_SGMII) && !PHY_FLAGS_TST(unit, port, PHY_FLAGS_COPPER)) { 713 PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER); 714 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 715 } else if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_FIBER)) { 716 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 717 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER); 718 } 719 720 if (REVERSE_MODE(pc)) { 721 SOC_IF_ERROR_RETURN 722 (_phy_54942_link_get(unit, port, link)); 723 } else { 724 if (PHY_WAN_MODE(unit, port)) { 725 /* WIS status */ 726 SOC_IF_ERROR_RETURN 727 (BSDK_RD_PHY84728_WIS_STATr(pc, &wis_mii_stat)); 728 bsdk_link = wis_mii_stat == 0xffff ? 0 : (wis_mii_stat & 0x0004) ? 1 : 0 ; 729 } else { 730 rv = bsdk_phy84728_link_get(pc, &bsdk_link); 731 if (!SOC_SUCCESS(rv)) { 732 return SOC_E_FAIL; 733 } 734 } 735 736 if (bsdk_link) { 737 *link = TRUE; 738 } else { 739 *link = FALSE; 740 } 741 } 742 743 LOG_VERBOSE(BSL_LS_SOC_PHY, 744 (BSL_META_U(unit, 745 "phy_84728_link_get: u=%d p=%d link=%d\n"), 746 unit, port, 747 *link)); 748 749 return SOC_E_NONE; 750 } 751 752 753 STATIC int 754 _phy_54942_enable_set(int unit, soc_port_t port, int enable) 755 { 756 phy_ctrl_t *pc; 757 758 pc = EXT_PHY_SW_STATE(unit, port); 759 760 /* disable the Tx */ 761 SOC_IF_ERROR_RETURN 762 (BSDK_MOD_PHY84728_XGXSBLK0_MISCCONTROL1r(pc, 763 enable? 0:XGXSBLK0_MISCCONTROL1_GLOBAL_PMD_TX_DISABLE_MASK, 764 XGXSBLK0_MISCCONTROL1_GLOBAL_PMD_TX_DISABLE_MASK)); 765 766 /* disable the Rx */ 767 SOC_IF_ERROR_RETURN 768 (BSDK_MOD_PHY84728_SYS_DEV4_XGXS_CTRLr(pc, enable? BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ : 0, 769 BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ )); 770 771 return SOC_E_NONE; 772 } 773 774 /* 775 * Function: 776 * phy_84728_enable_set 777 * Purpose: 778 * Enable or disable the physical interface. 779 * Parameters: 780 * unit - StrataSwitch unit #. 781 * port - StrataSwitch port #. 782 * enable - Boolean, true = enable PHY, false = disable. 783 * Returns: 784 * SOC_E_XXX 785 */ 786 787 STATIC int 788 phy_84728_enable_set(int unit, soc_port_t port, int enable) 789 { 790 phy_ctrl_t *pc; 791 uint16 power; 792 793 pc = EXT_PHY_SW_STATE(unit, port); 794 795 if (enable) { 796 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE); 797 } else { 798 PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE); 799 } 800 801 if (REVERSE_MODE(pc)) { 802 SOC_IF_ERROR_RETURN 803 (_phy_54942_enable_set(unit, port, enable)); 804 } else { 805 806 /* PMA/PMD */ 807 power = (enable) ? 0 : 0x0001 ; 808 SOC_IF_ERROR_RETURN( 809 BSDK_MOD_PHY84728_LN_DEV1_PMD_XMIT_DISABLEr(pc, power, 0x0001)); 810 811 } 812 813 if (enable) { 814 sal_usleep(50); 815 SOC_IF_ERROR_RETURN(_phy_84728_squelch_enable(unit, port, TRUE)); 816 } 817 818 if (NXT_PC(pc)) { 819 PHYDRV_CALL_ARG1(pc,PHY_ENABLE_SET,enable); 820 } 821 822 LOG_INFO(BSL_LS_SOC_PHY, 823 (BSL_META_U(unit, 824 "phy_84728_enable_set: " 825 "Power %s fiber medium\n"), (enable) ? "up" : "down")); 826 827 return SOC_E_NONE; 828 } 829 830 /* 831 * Function: 832 * phy_84728_duplex_set 833 * Purpose: 834 * Set the current duplex mode 835 * Parameters: 836 * unit - StrataSwitch unit #. 837 * port - StrataSwitch port #. 838 * duplex - Boolean, true indicates full duplex, false indicates half. 839 * Returns: 840 * SOC_E_NONE 841 * SOC_E_UNAVAIL - Half duplex requested, and not supported. 842 * Notes: 843 */ 844 STATIC int 845 phy_84728_duplex_set(int unit, soc_port_t port, int duplex_in) 846 { 847 int rv = SOC_E_NONE ; 848 phy_ctrl_t *pc; 849 bsdk_phy84728_duplex_t duplex; 850 uint16 mii_ctrl; 851 bsdk_phy84728_intf_t line_mode; 852 853 pc = EXT_PHY_SW_STATE(unit, port); 854 855 if (NXT_PC(pc)) { 856 PHYDRV_CALL_ARG1(pc,PHY_DUPLEX_SET, duplex_in); 857 return SOC_E_NONE; 858 } 859 860 if (duplex_in) { 861 duplex = BSDK_PHY84728_FULL_DUPLEX; 862 } else { 863 duplex = BSDK_PHY84728_HALF_DUPLEX; 864 } 865 866 867 SOC_IF_ERROR_RETURN( 868 bsdk_phy84728_line_intf_get(pc, 0, &line_mode)); 869 870 if ((line_mode == BSDK_PHY84728_INTF_1000X ) || 871 (line_mode == BSDK_PHY84728_INTF_SFI )) { 872 873 if (duplex == BSDK_PHY84728_FULL_DUPLEX) { 874 rv = SOC_E_NONE; 875 goto exit; 876 } else { 877 rv = SOC_E_UNAVAIL; 878 goto exit; 879 } 880 } 881 SOC_IF_ERROR_RETURN( 882 BSDK_RD_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, &mii_ctrl)); 883 884 if (duplex == BSDK_PHY84728_FULL_DUPLEX) { 885 mii_ctrl |= BSDK_PHY84728_AN_MII_CTRL_FD; 886 } else if (duplex == BSDK_PHY84728_HALF_DUPLEX) { 887 mii_ctrl &= ~BSDK_PHY84728_AN_MII_CTRL_FD; 888 } 889 SOC_IF_ERROR_RETURN( 890 BSDK_WR_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, mii_ctrl)); 891 892 exit: 893 894 if(SOC_SUCCESS(rv)) { 895 pc->copper.force_duplex = duplex_in; 896 } 897 898 899 LOG_INFO(BSL_LS_SOC_PHY, 900 (BSL_META_U(unit, 901 "phy_84728_duplex_set: u=%d p=%d d=%d rv=%d\n"), 902 unit, port, duplex, rv)); 903 return rv; 904 } 905 906 /* 907 * Function: 908 * phy_84728_duplex_get 909 * Purpose: 910 * Get the current operating duplex mode. If autoneg is enabled, 911 * then operating mode is returned, otherwise forced mode is returned. 912 * Parameters: 913 * unit - StrataSwitch unit #. 914 * port - StrataSwitch port #. 915 * duplex - (OUT) Boolean, true indicates full duplex, false 916 * indicates half. 917 * Returns: 918 * SOC_E_NONE 919 * Notes: 920 * The duplex is retrieved for the ACTIVE medium. 921 * No synchronization performed at this level. Autonegotiation is 922 * not manipulated. 923 */ 924 925 STATIC int 926 phy_84728_duplex_get(int unit, soc_port_t port, int *duplex) 927 { 928 929 phy_ctrl_t *pc; 930 uint16 status; 931 bsdk_phy84728_intf_t line_mode; 932 933 pc = EXT_PHY_SW_STATE(unit, port); 934 935 if (NXT_PC(pc)) { 936 PHYDRV_CALL_ARG1(pc,PHY_DUPLEX_GET, duplex); 937 return SOC_E_NONE; 938 } 939 940 SOC_IF_ERROR_RETURN( 941 bsdk_phy84728_line_intf_get(pc, 0, &line_mode)); 942 943 if ((line_mode == BSDK_PHY84728_INTF_1000X ) || 944 (line_mode == BSDK_PHY84728_INTF_SFI )) { 945 *duplex = TRUE; 946 } else { 947 SOC_IF_ERROR_RETURN( 948 BSDK_RD_PHY84728_LN_DEV7_AN_BASE1000X_STAT1r(pc, &status)); 949 if (status & (1U << 2)) { 950 *duplex = TRUE; 951 } else { 952 *duplex = FALSE; 953 } 954 } 955 956 return SOC_E_NONE; 957 } 958 959 960 /* 961 * Function: 962 * phy_84728_speed_set 963 * Purpose: 964 * Set PHY speed 965 * Parameters: 966 * unit - StrataSwitch unit #. 967 * port - StrataSwitch port #. 968 * speed - link speed in Mbps 969 * Returns: 970 * SOC_E_NONE 971 */ 972 STATIC int 973 phy_84728_speed_set(int unit, soc_port_t port, int speed) 974 { 975 phy_ctrl_t *pc; 976 phy_ctrl_t *int_pc; 977 int rv; 978 979 pc = EXT_PHY_SW_STATE(unit, port); 980 int_pc = INT_PHY_SW_STATE(unit, port); 981 rv = SOC_E_NONE; 982 983 if (speed > 10000) { 984 return SOC_E_UNAVAIL; 985 } 986 987 if (NXT_PC(pc)) { 988 PHYDRV_CALL_ARG1(pc,PHY_SPEED_SET,speed); 989 return SOC_E_NONE; 990 } 991 992 rv = bsdk_phy84728_speed_set(pc, speed); 993 if(SOC_SUCCESS(rv)) { 994 /* need to set the internal phy's speed accordingly */ 995 if (NULL != int_pc) { 996 if (REVERSE_MODE(pc)) { 997 SOC_IF_ERROR_RETURN 998 (PHY_INTERFACE_SET(int_pc->pd, unit, port, SOC_PORT_IF_SFI)); 999 } 1000 PHY_AUTO_NEGOTIATE_SET (int_pc->pd, unit, port, 0); 1001 PHY_SPEED_SET(int_pc->pd, unit, port, speed); 1002 } 1003 if(PHY_COPPER_MODE(unit, port)) { 1004 pc->copper.force_speed = speed; 1005 } else { 1006 if(PHY_FIBER_MODE(unit, port)) { 1007 pc->fiber.force_speed = speed; 1008 } 1009 } 1010 } 1011 LOG_INFO(BSL_LS_SOC_PHY, 1012 (BSL_META_U(unit, 1013 "phy_84728_speed_set: u=%d p=%d s=%d fiber=%d rv=%d\n"), 1014 unit, port, speed, PHY_FIBER_MODE(unit, port), rv)); 1015 1016 return rv; 1017 } 1018 1019 /* 1020 * Function: 1021 * phy_84728_speed_get 1022 * Purpose: 1023 * Get the current operating speed for a 84728 device. 1024 * Parameters: 1025 * unit - StrataSwitch unit #. 1026 * port - StrataSwitch port #. 1027 * speed - (OUT) Speed of the phy 1028 * Returns: 1029 * SOC_E_NONE 1030 * Notes: 1031 * The speed is retrieved for the ACTIVE medium. 1032 */ 1033 1034 STATIC int 1035 phy_84728_speed_get(int unit, soc_port_t port, int *speed) 1036 { 1037 phy_ctrl_t *pc; 1038 uint16 data = 0; 1039 bsdk_phy84728_intf_t line_mode; 1040 1041 if (speed == NULL) { 1042 return SOC_E_PARAM; 1043 } 1044 1045 pc = EXT_PHY_SW_STATE(unit, port); 1046 1047 if (NXT_PC(pc)) { 1048 PHYDRV_CALL_ARG1(pc,PHY_SPEED_GET,speed); 1049 return SOC_E_NONE; 1050 } 1051 1052 { 1053 SOC_IF_ERROR_RETURN( 1054 bsdk_phy84728_line_intf_get(pc, 0, &line_mode)); 1055 1056 if (line_mode == BSDK_PHY84728_INTF_SFI) { 1057 *speed = 10000; 1058 return SOC_E_NONE; 1059 } 1060 if (line_mode == BSDK_PHY84728_INTF_1000X) { 1061 *speed = 1000; 1062 return SOC_E_NONE; 1063 } 1064 SOC_IF_ERROR_RETURN( 1065 BSDK_RD_PHY84728_LN_DEV1_SPEED_LINK_DETECT_STATr(pc, &data)); 1066 switch(data & BSDK_PHY84728_PMD_SPEED_LD_STAT_LN_PDM_SPEED_MASK) { 1067 case BSDK_PHY84728_PMD_SPEED_LD_STAT_LN_PDM_SPEED_10M: 1068 *speed = 10; 1069 break; 1070 case BSDK_PHY84728_PMD_SPEED_LD_STAT_LN_PDM_SPEED_100M: 1071 *speed = 100; 1072 break; 1073 case BSDK_PHY84728_PMD_SPEED_LD_STAT_LN_PDM_SPEED_1G: 1074 *speed = 1000; 1075 break; 1076 case BSDK_PHY84728_PMD_SPEED_LD_STAT_LN_PDM_SPEED_10G: 1077 *speed = 10000; 1078 break; 1079 default : 1080 *speed = 0; 1081 break; 1082 } 1083 } 1084 1085 LOG_INFO(BSL_LS_SOC_PHY, 1086 (BSL_META_U(unit, 1087 "phy_84728_speed_get: u=%d p=%d speed=%d"), 1088 unit, port, *speed)); 1089 1090 return SOC_E_NONE; 1091 } 1092 1093 /* 1094 * Function: 1095 * phy_84728_an_set 1096 * Purpose: 1097 * Enable or disable auto-negotiation on the specified port. 1098 * Parameters: 1099 * unit - StrataSwitch unit #. 1100 * port - StrataSwitch port #. 1101 * autoneg - Boolean, if true, auto-negotiation is enabled 1102 * (and/or restarted). If false, autonegotiation is disabled. 1103 * Returns: 1104 * SOC_E_XXX 1105 * Notes: 1106 * The autoneg mode is set only for the ACTIVE medium. 1107 */ 1108 1109 STATIC int 1110 phy_84728_an_set(int unit, soc_port_t port, int autoneg) 1111 { 1112 int rv; 1113 phy_ctrl_t *pc; 1114 uint16 data = 0; 1115 bsdk_phy84728_intf_t line_mode; 1116 1117 pc = EXT_PHY_SW_STATE(unit, port); 1118 rv = SOC_E_NONE; 1119 1120 if (NXT_PC(pc)) { 1121 PHYDRV_CALL_ARG1(pc, PHY_AUTO_NEGOTIATE_SET, autoneg); 1122 return SOC_E_NONE; 1123 } 1124 1125 SOC_IF_ERROR_RETURN( 1126 bsdk_phy84728_line_intf_get(pc, 0, &line_mode)); 1127 1128 1129 if (line_mode == BSDK_PHY84728_INTF_SGMII) { 1130 return SOC_E_NONE; 1131 } 1132 1133 SOC_IF_ERROR_RETURN 1134 (BSDK_MOD_PHY84728_LN_DEV7_ANr(pc, 0x8308, autoneg ? 0x0 : 0x1c, 0x1f)); 1135 1136 SOC_IF_ERROR_RETURN 1137 (BSDK_MOD_PHY84728_LN_DEV7_AN_MSIC2r(pc, autoneg ? 0x0 : 0x20, 0x20)); 1138 1139 1140 #if 0 /* needed for KR */ 1141 SOC_IF_ERROR_RETURN( 1142 BSDK_RD_PHY84728_XFI_DEV7_AN_CTRLr(pc, &data)); 1143 if (autoneg) { 1144 data |= (BSDK_PHY84728_AN_AN_CTRL_AE | 1145 BSDK_PHY84728_AN_AN_CTRL_RAN); 1146 } else { 1147 data &= ~(BSDK_PHY84728_AN_AN_CTRL_AE | 1148 BSDK_PHY84728_AN_AN_CTRL_RAN); 1149 } 1150 SOC_IF_ERROR_RETURN( 1151 BSDK_WR_PHY84728_XFI_DEV7_AN_CTRLr(pc, data)); 1152 #endif 1153 1154 1155 SOC_IF_ERROR_RETURN( 1156 BSDK_RD_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, &data)); 1157 if (autoneg) { 1158 data |= (BSDK_PHY84728_AN_MII_CTRL_AE | 1159 BSDK_PHY84728_AN_MII_CTRL_RAN); 1160 } else { 1161 data &= ~(BSDK_PHY84728_AN_MII_CTRL_AE | 1162 BSDK_PHY84728_AN_MII_CTRL_RAN); 1163 } 1164 SOC_IF_ERROR_RETURN( 1165 BSDK_WR_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, data)); 1166 1167 if(SOC_SUCCESS(rv)) { 1168 if(PHY_COPPER_MODE(unit, port)) { 1169 pc->copper.autoneg_enable = autoneg ? TRUE : FALSE; 1170 } else { 1171 if(PHY_FIBER_MODE(unit, port)) { 1172 pc->fiber.autoneg_enable = autoneg ? TRUE : FALSE; 1173 } 1174 } 1175 } 1176 1177 LOG_INFO(BSL_LS_SOC_PHY, 1178 (BSL_META_U(unit, 1179 "phy_84728_an_set: u=%d p=%d autoneg=%d rv=%d\n"), 1180 unit, port, autoneg, rv)); 1181 return rv; 1182 } 1183 1184 /* 1185 * Function: 1186 * phy_84728_an_get 1187 * Purpose: 1188 * Get the current auto-negotiation status (enabled/busy). 1189 * Parameters: 1190 * unit - StrataSwitch unit #. 1191 * port - StrataSwitch port #. 1192 * autoneg - (OUT) if true, auto-negotiation is enabled. 1193 * autoneg_done - (OUT) if true, auto-negotiation is complete. This 1194 * value is undefined if autoneg == FALSE. 1195 * Returns: 1196 * SOC_E_XXX 1197 * Notes: 1198 * The autoneg mode is retrieved for the ACTIVE medium. 1199 */ 1200 1201 STATIC int 1202 phy_84728_an_get(int unit, soc_port_t port, 1203 int *autoneg, int *autoneg_done) 1204 { 1205 int rv; 1206 phy_ctrl_t *pc; 1207 #if 0 1208 uint16 an_ctrl = 0, an_stat = 0; 1209 #endif 1210 uint16 an_mii_ctrl = 0, an_mii_stat = 0; 1211 bsdk_phy84728_intf_t line_mode; 1212 1213 pc = EXT_PHY_SW_STATE(unit, port); 1214 1215 rv = SOC_E_NONE; 1216 *autoneg = FALSE; 1217 *autoneg_done = FALSE; 1218 1219 if (NXT_PC(pc)) { 1220 PHYDRV_CALL_ARG2(pc, PHY_AUTO_NEGOTIATE_GET, autoneg, autoneg_done); 1221 return SOC_E_NONE; 1222 } 1223 1224 SOC_IF_ERROR_RETURN( 1225 bsdk_phy84728_line_intf_get(pc, 0, &line_mode)); 1226 1227 /* revisit for KR */ 1228 #if 0 1229 if (line_mode == BSDK_PHY84728_INTF_SFI) { 1230 SOC_IF_ERROR_RETURN( 1231 BSDK_RD_PHY84728_LN_DEV7_AN_CTRLr(pc, &an_ctrl)); 1232 SOC_IF_ERROR_RETURN( 1233 BSDK_RD_PHY84728_LN_DEV7_AN_STATr(pc, &an_stat)); 1234 *autoneg = (an_ctrl & BSDK_PHY84728_AN_AN_CTRL_AE) ? 1 : 0; 1235 *autoneg_done = (an_stat & BSDK_PHY84728_AN_AN_STAT_AN_DONE) ? 1 : 0; 1236 } else { 1237 #endif 1238 { 1239 SOC_IF_ERROR_RETURN( 1240 BSDK_RD_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, &an_mii_ctrl)); 1241 SOC_IF_ERROR_RETURN( 1242 BSDK_RD_PHY84728_LN_DEV7_AN_MII_STATr(pc, &an_mii_stat)); 1243 *autoneg = (an_mii_ctrl & BSDK_PHY84728_AN_MII_CTRL_AE) ? 1 : 0; 1244 *autoneg_done = 1245 (an_mii_stat & BSDK_PHY84728_AN_MII_STAT_AN_DONE) ? 1 : 0; 1246 } 1247 1248 return rv; 1249 } 1250 1251 1252 STATIC int 1253 _phy_54942_lb_set(int unit, soc_port_t port, int enable) 1254 { 1255 phy_ctrl_t *pc; 1256 1257 pc = EXT_PHY_SW_STATE(unit, port); 1258 1259 SOC_IF_ERROR_RETURN 1260 (BSDK_PHY84728_REG_MOD(pc, 1261 0x0, 0x4, 0, enable ? (1U << 14) : 0, (1U << 14))); 1262 1263 return SOC_E_NONE; 1264 } 1265 /* 1266 * Function: 1267 * phy_84728_lb_set 1268 * Purpose: 1269 * Set the local PHY loopback mode. 1270 * Parameters: 1271 * unit - StrataSwitch unit #. 1272 * port - StrataSwitch port #. 1273 * loopback - Boolean: true = enable loopback, false = disable. 1274 * Returns: 1275 * SOC_E_XXX 1276 * Notes: 1277 * The loopback mode is set only for the ACTIVE medium. 1278 * No synchronization performed at this level. 1279 */ 1280 1281 STATIC int 1282 phy_84728_lb_set(int unit, soc_port_t port, int enable) 1283 { 1284 int rv; 1285 phy_ctrl_t *pc; 1286 uint16 data = 0; 1287 bsdk_phy84728_intf_t line_mode; 1288 1289 pc = EXT_PHY_SW_STATE(unit, port); 1290 rv = SOC_E_NONE; 1291 1292 if (NXT_PC(pc)) { 1293 PHYDRV_CALL_ARG1(pc,PHY_LOOPBACK_SET,enable); 1294 if (enable) { 1295 SOC_IF_ERROR_RETURN 1296 (phy_84728_link_up(unit, port)); 1297 } 1298 return SOC_E_NONE; 1299 } 1300 1301 #if 1 1302 /* Disable(Enable) Squelch when we Enable(Disable) loopback */ 1303 SOC_IF_ERROR_RETURN 1304 (_phy_84728_squelch_enable(unit, port, enable ? FALSE : TRUE)); 1305 #endif 1306 1307 SOC_IF_ERROR_RETURN( 1308 bsdk_phy84728_line_intf_get(pc, 0, &line_mode)); 1309 1310 if (REVERSE_MODE(pc)) { 1311 SOC_IF_ERROR_RETURN 1312 (_phy_54942_lb_set(unit, port, enable)); 1313 1314 if (rv == SOC_E_NONE) { 1315 /* wait for link up when loopback is enabled */ 1316 1317 if (enable) { 1318 sal_usleep(2000000); 1319 } 1320 } 1321 } else { 1322 1323 /* lock detect bypass */ 1324 SOC_IF_ERROR_RETURN( 1325 BSDK_PHY84728_REG_MOD(pc, 0x00, 0x0001, 1326 0xCA7B, enable ? (1<<14) : 0, (1<<14))); 1327 1328 1329 if (line_mode == BSDK_PHY84728_INTF_SFI) { 1330 SOC_IF_ERROR_RETURN( 1331 BSDK_RD_PHY84728_LN_DEV1_PMD_CTRLr(pc, &data)); 1332 data &= ~(1); 1333 data |= (enable) ? 1 : 0x0000; 1334 SOC_IF_ERROR_RETURN( 1335 BSDK_WR_PHY84728_LN_DEV1_PMD_CTRLr(pc, data)); 1336 } else { 1337 SOC_IF_ERROR_RETURN( 1338 BSDK_RD_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, &data)); 1339 data &= ~BSDK_PHY84728_AN_MII_CTRL_LE; 1340 data |= (enable) ? BSDK_PHY84728_AN_MII_CTRL_LE : 0; 1341 SOC_IF_ERROR_RETURN( 1342 BSDK_WR_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, data)); 1343 if (!enable) 1344 { 1345 SOC_IF_ERROR_RETURN( 1346 BSDK_PHY84728_REG_MOD(pc, 0x00, 0x0001, 0xC8E4, (1 << 12), (1 << 12))); 1347 SOC_IF_ERROR_RETURN( 1348 BSDK_PHY84728_REG_MOD(pc, 0x00, 0x0001, 0xC8E4, (1 << 4), (1 << 4))); 1349 SOC_IF_ERROR_RETURN( 1350 BSDK_PHY84728_REG_MOD(pc, 0x00, 0x0001, 0xC8E4, 0, (1 << 12))); 1351 SOC_IF_ERROR_RETURN( 1352 BSDK_PHY84728_REG_MOD(pc, 0x00, 0x0001, 0xC8E4, 0, (1 << 4))); 1353 } 1354 } 1355 1356 if (rv == SOC_E_NONE) { 1357 /* wait for link up when loopback is enabled */ 1358 1359 if (enable) { 1360 sal_usleep(2000000); 1361 } 1362 } 1363 } 1364 1365 LOG_INFO(BSL_LS_SOC_PHY, 1366 (BSL_META_U(unit, 1367 "phy_84728_lb_set: u=%d p=%d en=%d rv=%d\n"), 1368 unit, port, enable, rv)); 1369 1370 return rv; 1371 } 1372 1373 STATIC int 1374 _phy_54942_lb_get(int unit, soc_port_t port, int *enable) 1375 { 1376 phy_ctrl_t *pc; 1377 uint16 tmp; 1378 1379 pc = EXT_PHY_SW_STATE(unit, port); 1380 1381 SOC_IF_ERROR_RETURN 1382 (BSDK_PHY84728_REG_RD(pc, 0x0, 0x4, 0, &tmp)); 1383 1384 *enable = tmp & (1U << 14) ? TRUE : FALSE; 1385 1386 return SOC_E_NONE; 1387 } 1388 1389 /* 1390 * Function: 1391 * phy_84728_lb_get 1392 * Purpose: 1393 * Get the local PHY loopback mode. 1394 * Parameters: 1395 * unit - StrataSwitch unit #. 1396 * port - StrataSwitch port #. 1397 * loopback - (OUT) Boolean: true = enable loopback, false = disable. 1398 * Returns: 1399 * SOC_E_XXX 1400 * Notes: 1401 * The loopback mode is retrieved for the ACTIVE medium. 1402 */ 1403 1404 STATIC int 1405 phy_84728_lb_get(int unit, soc_port_t port, int *enable) 1406 { 1407 int rv; 1408 phy_ctrl_t *pc; 1409 uint16 data = 0; 1410 bsdk_phy84728_intf_t line_mode; 1411 1412 pc = EXT_PHY_SW_STATE(unit, port); 1413 rv = SOC_E_NONE; 1414 1415 if (NXT_PC(pc)) { 1416 PHYDRV_CALL_ARG1(pc,PHY_LOOPBACK_GET,enable); 1417 return SOC_E_NONE; 1418 } 1419 1420 SOC_IF_ERROR_RETURN( 1421 bsdk_phy84728_line_intf_get(pc, 0, &line_mode)); 1422 1423 if (REVERSE_MODE(pc)) { 1424 SOC_IF_ERROR_RETURN 1425 (_phy_54942_lb_get(unit, port, enable)); 1426 } else { 1427 if (line_mode == BSDK_PHY84728_INTF_SFI) { 1428 SOC_IF_ERROR_RETURN( 1429 BSDK_RD_PHY84728_LN_DEV1_PMD_CTRLr(pc, &data)); 1430 *enable = (data & 1) ? 1 : 0; 1431 } else { 1432 SOC_IF_ERROR_RETURN( 1433 BSDK_RD_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, &data)); 1434 *enable = (data & BSDK_PHY84728_AN_MII_CTRL_LE) ? 1 : 0; 1435 } 1436 } 1437 1438 return rv; 1439 } 1440 1441 STATIC int 1442 _phy_84728_control_pdet_set(int unit, soc_port_t port, uint32 enable) 1443 { 1444 uint16 mask; 1445 uint16 data; 1446 phy_ctrl_t *pc; /* PHY software state */ 1447 1448 mask = PHY84728_PDET_MASK; 1449 data = enable ? mask : 0; 1450 1451 pc = EXT_PHY_SW_STATE(unit, port); 1452 1453 SOC_IF_ERROR_RETURN( 1454 BSDK_MOD_PHY84728_LN_DEV7_AN_BASE1000X_CTRL2r(pc, data, mask)); 1455 1456 return SOC_E_NONE; 1457 } 1458 1459 STATIC int 1460 _phy_84728_control_pdet_get(int unit, soc_port_t port, uint32 *value) 1461 { 1462 uint16 data16; 1463 phy_ctrl_t *pc; /* PHY software state */ 1464 1465 pc = EXT_PHY_SW_STATE(unit, port); 1466 1467 SOC_IF_ERROR_RETURN( 1468 BSDK_RD_PHY84728_LN_DEV7_AN_BASE1000X_CTRL2r(pc, &data16)); 1469 1470 if ((data16 & PHY84728_PDET_MASK) == PHY84728_PDET_MASK) { 1471 *value = 1; 1472 } else { 1473 *value = 0; 1474 } 1475 1476 return SOC_E_NONE; 1477 } 1478 1479 1480 STATIC int 1481 _phy_84728_control_edc_mode_get(int unit, soc_port_t port, uint32 *value) 1482 { 1483 uint16 data16; 1484 phy_ctrl_t *pc; /* PHY software state */ 1485 1486 pc = EXT_PHY_SW_STATE(unit, port); 1487 1488 /* program EDC mode */ 1489 SOC_IF_ERROR_RETURN 1490 (READ_PHY84728_PMA_PMD_REG(unit,pc, 0xCA1A,&data16)); 1491 1492 *value = data16 & PHY_84727_EDC_MODE_MASK; 1493 return SOC_E_NONE; 1494 } 1495 1496 STATIC int 1497 _phy_84728_control_edc_mode_set(int unit, soc_port_t port, uint32 value) 1498 { 1499 uint16 data16; 1500 uint16 mask16; 1501 phy_ctrl_t *pc; /* PHY software state */ 1502 1503 pc = EXT_PHY_SW_STATE(unit, port); 1504 1505 /* EDC mode programming sequence*/ 1506 mask16 = 1 << 9; 1507 1508 /* induce LOS condition: toggle register bit 0xc800.9 */ 1509 SOC_IF_ERROR_RETURN 1510 (READ_PHY84728_PMA_PMD_REG(unit,pc, 0xC800,&data16)); 1511 /* only change toggled bit 9 */ 1512 SOC_IF_ERROR_RETURN 1513 (MODIFY_PHY84728_PMA_PMD_REG(unit,pc, 0xC800,~data16,mask16)); 1514 1515 /* program EDC mode */ 1516 SOC_IF_ERROR_RETURN 1517 (MODIFY_PHY84728_PMA_PMD_REG(unit,pc, 0xCA1A,(uint16)value, 1518 PHY_84727_EDC_MODE_MASK)); 1519 1520 /* remove LOS condition: restore back original value of bit 0xc800.9 */ 1521 SOC_IF_ERROR_RETURN 1522 (MODIFY_PHY84728_PMA_PMD_REG(unit,pc, 0xC800,data16,mask16)); 1523 1524 return SOC_E_NONE; 1525 } 1526 1527 STATIC int 1528 _phy_84728_mode_set(int unit, soc_port_t port, uint32 mode) { 1529 uint16 dev_reg, mask; 1530 phy_ctrl_t *pc; 1531 1532 pc = EXT_PHY_SW_STATE(unit, port); 1533 1534 switch(mode) { 1535 case WAN_MODE: 1536 if (PHY_WAN_MODE(unit, port)) { 1537 /* Already in WAN mode */ 1538 return SOC_E_NONE; 1539 } 1540 SOC_IF_ERROR_RETURN 1541 (BSDK_RD_PHY84728_WIS_DEV_IN_PKGr(pc, &dev_reg)); 1542 #if 0 1543 /* Check WIS present */ 1544 if (!(dev_reg & 0x0004)) { 1545 return SOC_E_UNAVAIL; 1546 } 1547 #endif 1548 /* To configure WAN mode clock, */ 1549 mask = PMD_MISC_CTRL_WAN_MODE; 1550 SOC_IF_ERROR_RETURN 1551 (BSDK_MOD_PHY84728_PMD_MISC_CTRLr(pc, PMD_MISC_CTRL_WAN_MODE, mask)); 1552 1553 PHY_FLAGS_SET(unit, port, PHY_FLAGS_WAN); 1554 break; 1555 1556 case LAN_MODE: 1557 #if 0 1558 if (!PHY_WAN_MODE(unit, port)) { 1559 /* Already in LAN mode */ 1560 return SOC_E_NONE; 1561 } 1562 #endif 1563 1564 /* To configure LAN mode clock, */ 1565 mask = PMD_MISC_CTRL_WAN_MODE; 1566 1567 /* put device in LAN mode */ 1568 SOC_IF_ERROR_RETURN 1569 (BSDK_MOD_PHY84728_PMD_MISC_CTRLr(pc, 0, mask)); 1570 1571 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_WAN); 1572 break; 1573 default: 1574 return SOC_E_UNAVAIL; 1575 } 1576 1577 LOG_INFO(BSL_LS_SOC_PHY, 1578 (BSL_META_U(unit, 1579 "phy_84728_mode_set: u=%d port=%d mode=%d\n"), 1580 unit, port, mode)); 1581 1582 return SOC_E_NONE; 1583 } 1584 1585 1586 /* 1587 * Function: 1588 * phy_84728_medium_config_set 1589 * Purpose: 1590 * Set the operating parameters that are automatically selected 1591 * when medium switches type. 1592 * Parameters: 1593 * unit - StrataSwitch unit # 1594 * port - Port number 1595 * medium - SOC_PORT_MEDIUM_COPPER/FIBER 1596 * cfg - Operating parameters 1597 * Returns: 1598 * SOC_E_XXX 1599 */ 1600 1601 STATIC int 1602 phy_84728_medium_config_set(int unit, soc_port_t port, 1603 soc_port_medium_t medium, 1604 soc_phy_config_t *cfg) 1605 { 1606 phy_ctrl_t *pc; 1607 #if 0 1608 soc_phy_config_t *active_medium; /* Currently active medium */ 1609 #endif 1610 soc_phy_config_t *change_medium; /* Requested medium */ 1611 soc_phy_config_t *other_medium; /* The other medium */ 1612 1613 soc_port_mode_t advert_mask; 1614 1615 if (NULL == cfg) { 1616 return SOC_E_PARAM; 1617 } 1618 1619 pc = EXT_PHY_SW_STATE(unit, port); 1620 1621 if (NXT_PC(pc)) { 1622 PHYDRV_CALL_ARG2(pc, PHY_MEDIUM_CONFIG_SET, medium, cfg); 1623 return SOC_E_NONE; 1624 } 1625 1626 switch (medium) { 1627 case SOC_PORT_MEDIUM_COPPER: 1628 if (!pc->automedium && !PHY_COPPER_MODE(unit, port)) { 1629 return SOC_E_UNAVAIL; 1630 } 1631 change_medium = &pc->copper; 1632 other_medium = &pc->fiber; 1633 advert_mask = ADVERT_ALL_COPPER; 1634 break; 1635 case SOC_PORT_MEDIUM_FIBER: 1636 if (!pc->automedium && !PHY_FIBER_MODE(unit, port)) { 1637 return SOC_E_UNAVAIL; 1638 } 1639 change_medium = &pc->fiber; 1640 other_medium = &pc->copper; 1641 advert_mask = ADVERT_ALL_FIBER; 1642 break; 1643 default: 1644 return SOC_E_PARAM; 1645 } 1646 1647 /* 1648 * Changes take effect immediately if the target medium is active or 1649 * the preferred medium changes. 1650 */ 1651 if (change_medium->preferred != cfg->preferred) { 1652 /* Make sure that only one medium is preferred */ 1653 other_medium->preferred = !cfg->preferred; 1654 } 1655 1656 sal_memcpy(change_medium, cfg, sizeof(*change_medium)); 1657 change_medium->autoneg_advert &= advert_mask; 1658 1659 return SOC_E_NONE; 1660 } 1661 1662 /* 1663 * Function: 1664 * phy_84728_medium_config_get 1665 * Purpose: 1666 * Get the operating parameters that are automatically selected 1667 * when medium switches type. 1668 * Parameters: 1669 * unit - StrataSwitch unit # 1670 * port - Port number 1671 * medium - SOC_PORT_MEDIUM_COPPER/FIBER 1672 * cfg - (OUT) Operating parameters 1673 * Returns: 1674 * SOC_E_XXX 1675 */ 1676 1677 STATIC int 1678 phy_84728_medium_config_get(int unit, soc_port_t port, 1679 soc_port_medium_t medium, 1680 soc_phy_config_t *cfg) 1681 { 1682 int rv; 1683 phy_ctrl_t *pc; 1684 1685 pc = EXT_PHY_SW_STATE(unit, port); 1686 rv = SOC_E_NONE; 1687 1688 if (NXT_PC(pc)) { 1689 PHYDRV_CALL_ARG2(pc, PHY_MEDIUM_CONFIG_GET, medium, cfg); 1690 return SOC_E_NONE; 1691 } 1692 1693 switch (medium) { 1694 case SOC_PORT_MEDIUM_COPPER: 1695 if (pc->automedium || PHY_COPPER_MODE(unit, port)) { 1696 sal_memcpy(cfg, &pc->copper, sizeof (*cfg)); 1697 } else { 1698 rv = SOC_E_UNAVAIL; 1699 } 1700 break; 1701 case SOC_PORT_MEDIUM_FIBER: 1702 if (pc->automedium || PHY_FIBER_MODE(unit, port)) { 1703 sal_memcpy(cfg, &pc->fiber, sizeof (*cfg)); 1704 } else { 1705 rv = SOC_E_UNAVAIL; 1706 } 1707 break; 1708 default: 1709 rv = SOC_E_PARAM; 1710 break; 1711 } 1712 1713 return rv; 1714 } 1715 1716 /* 1717 * Function: 1718 * phy_84728_ability_advert_set 1719 * Purpose: 1720 * Set the current advertisement for auto-negotiation. 1721 * Parameters: 1722 * unit - StrataSwitch unit #. 1723 * port - StrataSwitch port #. 1724 * mode - Port mode mask indicating supported options/speeds. 1725 * Returns: 1726 * SOC_E_XXX 1727 * Notes: 1728 * The advertisement is set only for the ACTIVE medium. 1729 * No synchronization performed at this level. 1730 */ 1731 STATIC int 1732 phy_84728_ability_advert_set(int unit, soc_port_t port,soc_port_ability_t *ability) 1733 { 1734 int rv; 1735 phy_ctrl_t *pc; 1736 bsdk_phy84728_port_ability_t local_ability; 1737 1738 pc = EXT_PHY_SW_STATE(unit, port); 1739 1740 if (NULL == ability) { 1741 return (SOC_E_PARAM); 1742 } 1743 1744 if (NXT_PC(pc)) { 1745 PHYDRV_CALL_ARG1(pc,PHY_ABILITY_ADVERT_SET,ability); 1746 return SOC_E_NONE; 1747 } 1748 1749 if (PHY_COPPER_MODE(unit, port)) { 1750 pc->copper.advert_ability = *ability; 1751 } else { 1752 pc->fiber.advert_ability = *ability; 1753 } 1754 1755 local_ability = 0; 1756 1757 if(ability->speed_full_duplex & SOC_PA_SPEED_1000MB) { 1758 local_ability |= BSDK_PHY84728_PA_1000MB_FD; 1759 } 1760 if(ability->speed_full_duplex & SOC_PA_SPEED_10GB) { 1761 local_ability |= BSDK_PHY84728_PA_10000MB_FD; 1762 } 1763 1764 if(ability->pause & SOC_PA_PAUSE_TX) { 1765 local_ability |= BSDK_PHY84728_PA_PAUSE_TX; 1766 } 1767 if(ability->pause & SOC_PA_PAUSE_RX) { 1768 local_ability |= BSDK_PHY84728_PA_PAUSE_RX; 1769 } 1770 if(ability->pause & SOC_PA_PAUSE_ASYMM) { 1771 local_ability |= BSDK_PHY84728_PA_PAUSE_ASYMM; 1772 } 1773 1774 if(ability->loopback & SOC_PA_LB_NONE) { 1775 local_ability |= BSDK_PHY84728_PA_LB_NONE; 1776 } 1777 if(ability->loopback & SOC_PA_LB_PHY) { 1778 local_ability |= BSDK_PHY84728_PA_LB_PHY; 1779 } 1780 if(ability->flags & SOC_PA_AUTONEG) { 1781 local_ability |= BSDK_PHY84728_PA_AN; 1782 } 1783 1784 rv = bsdk_phy84728_ability_advert_set(pc, local_ability); 1785 1786 return rv; 1787 } 1788 1789 /* 1790 * Function: 1791 * phy_84728_ability_advert_get 1792 * Purpose: 1793 * Get the current advertisement for auto-negotiation. 1794 * Parameters: 1795 * unit - StrataSwitch unit #. 1796 * port - StrataSwitch port #. 1797 * mode - (OUT) Port mode mask indicating supported options/speeds. 1798 * Returns: 1799 * SOC_E_XXX 1800 * Notes: 1801 * The advertisement is retrieved for the ACTIVE medium. 1802 * No synchronization performed at this level. 1803 */ 1804 STATIC int 1805 phy_84728_ability_advert_get(int unit, soc_port_t port,soc_port_ability_t *ability) 1806 { 1807 phy_ctrl_t *pc; 1808 int rv; 1809 bsdk_phy84728_port_ability_t local_ability; 1810 1811 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 1812 return SOC_E_NONE; 1813 } 1814 1815 if (NULL == ability) { 1816 return (SOC_E_PARAM); 1817 } 1818 1819 pc = EXT_PHY_SW_STATE(unit, port); 1820 1821 if (NXT_PC(pc)) { 1822 PHYDRV_CALL_ARG1(pc,PHY_ABILITY_ADVERT_GET,ability); 1823 return SOC_E_NONE; 1824 } 1825 1826 local_ability = 0; 1827 1828 rv = bsdk_phy84728_ability_advert_get(pc, &local_ability); 1829 if (rv != SOC_E_NONE) { 1830 return SOC_E_FAIL; 1831 } 1832 1833 if(local_ability & BSDK_PHY84728_PA_1000MB_FD) { 1834 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 1835 } 1836 if(local_ability & BSDK_PHY84728_PA_10000MB_FD) { 1837 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 1838 } 1839 1840 if(local_ability & BSDK_PHY84728_PA_PAUSE_TX) { 1841 ability->pause |= SOC_PA_PAUSE_TX; 1842 } 1843 if(local_ability & BSDK_PHY84728_PA_PAUSE_RX) { 1844 ability->pause |= SOC_PA_PAUSE_RX; 1845 } 1846 if(local_ability & BSDK_PHY84728_PA_PAUSE_ASYMM) { 1847 ability->pause |= SOC_PA_PAUSE_ASYMM; 1848 } 1849 1850 if(local_ability & BSDK_PHY84728_PA_LB_NONE) { 1851 ability->loopback |= SOC_PA_LB_NONE; 1852 } 1853 if(local_ability & BSDK_PHY84728_PA_LB_PHY) { 1854 ability->loopback |= SOC_PA_LB_PHY; 1855 } 1856 if(local_ability & BSDK_PHY84728_PA_AN) { 1857 ability->flags = SOC_PA_AUTONEG; 1858 } 1859 1860 return SOC_E_NONE; 1861 } 1862 1863 /* 1864 * Function: 1865 * phy_84728_ability_remote_get 1866 * Purpose: 1867 * Get the current remote advertisement for auto-negotiation. 1868 * Parameters: 1869 * unit - StrataSwitch unit #. 1870 * port - StrataSwitch port #. 1871 * mode - (OUT) Port mode mask indicating supported options/speeds. 1872 * Returns: 1873 * SOC_E_XXX 1874 * Notes: 1875 * The advertisement is retrieved for the ACTIVE medium. 1876 * No synchronization performed at this level. 1877 */ 1878 STATIC int 1879 phy_84728_ability_remote_get(int unit, soc_port_t port,soc_port_ability_t *ability) 1880 { 1881 phy_ctrl_t *pc; 1882 int rv; 1883 bsdk_phy84728_port_ability_t remote_ability; 1884 1885 if (NULL == ability) { 1886 return (SOC_E_PARAM); 1887 } 1888 1889 pc = EXT_PHY_SW_STATE(unit, port); 1890 1891 if (NXT_PC(pc)) { 1892 PHYDRV_CALL_ARG1(pc,PHY_ABILITY_REMOTE_GET,ability); 1893 return SOC_E_NONE; 1894 } 1895 1896 remote_ability = 0; 1897 1898 rv = bsdk_phy84728_remote_ability_advert_get(pc, 1899 &remote_ability); 1900 if (rv != SOC_E_NONE) { 1901 return SOC_E_FAIL; 1902 } 1903 1904 if(remote_ability & BSDK_PHY84728_PA_1000MB_FD) { 1905 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 1906 } 1907 if(remote_ability & BSDK_PHY84728_PA_10000MB_FD) { 1908 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 1909 } 1910 1911 if(remote_ability & BSDK_PHY84728_PA_PAUSE_TX) { 1912 ability->pause |= SOC_PA_PAUSE_TX; 1913 } 1914 if(remote_ability & BSDK_PHY84728_PA_PAUSE_RX) { 1915 ability->pause |= SOC_PA_PAUSE_RX; 1916 } 1917 if(remote_ability & BSDK_PHY84728_PA_PAUSE_ASYMM) { 1918 ability->pause |= SOC_PA_PAUSE_ASYMM; 1919 } 1920 1921 if(remote_ability & BSDK_PHY84728_PA_LB_NONE) { 1922 ability->loopback |= SOC_PA_LB_NONE; 1923 } 1924 if(remote_ability & BSDK_PHY84728_PA_LB_PHY) { 1925 ability->loopback |= SOC_PA_LB_PHY; 1926 } 1927 if(remote_ability & BSDK_PHY84728_PA_AN) { 1928 ability->flags = SOC_PA_AUTONEG; 1929 } 1930 1931 return SOC_E_NONE; 1932 } 1933 1934 1935 1936 /* 1937 * Function: 1938 * phy_84728_ability_local_get 1939 * Purpose: 1940 * Get local abilities 1941 * Parameters: 1942 * unit - StrataSwitch unit #. 1943 * port - StrataSwitch port #. 1944 * mode - (OUT) Port mode mask indicating supported options/speeds. 1945 * Returns: 1946 * SOC_E_NONE 1947 * Notes: 1948 * The ability is retrieved only for the ACTIVE medium. 1949 */ 1950 1951 STATIC int 1952 phy_84728_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability) 1953 { 1954 int rv = SOC_E_NONE; 1955 phy_ctrl_t *pc; 1956 bsdk_phy84728_port_ability_t local_ability = 0; 1957 1958 if (NULL == ability) { 1959 return SOC_E_PARAM; 1960 } 1961 1962 pc = EXT_PHY_SW_STATE(unit, port); 1963 1964 if (NXT_PC(pc)) { 1965 PHYDRV_CALL_ARG1(pc,PHY_ABILITY_LOCAL_GET,ability); 1966 return SOC_E_NONE; 1967 } 1968 1969 rv = bsdk_phy84728_ability_local_get(pc, &local_ability); 1970 if (rv != SOC_E_NONE) { 1971 return SOC_E_FAIL; 1972 } 1973 1974 if(local_ability & BSDK_PHY84728_PA_1000MB_FD) { 1975 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 1976 } 1977 if(local_ability & BSDK_PHY84728_PA_10000MB_FD) { 1978 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 1979 } 1980 1981 if(local_ability & BSDK_PHY84728_PA_PAUSE_TX) { 1982 ability->pause |= SOC_PA_PAUSE_TX; 1983 } 1984 if(local_ability & BSDK_PHY84728_PA_PAUSE_RX) { 1985 ability->pause |= SOC_PA_PAUSE_RX; 1986 } 1987 if(local_ability & BSDK_PHY84728_PA_PAUSE_ASYMM) { 1988 ability->pause |= SOC_PA_PAUSE_ASYMM; 1989 } 1990 if(local_ability & BSDK_PHY84728_PA_LB_NONE) { 1991 ability->loopback |= SOC_PA_LB_NONE; 1992 } 1993 if(local_ability & BSDK_PHY84728_PA_LB_PHY) { 1994 ability->loopback |= SOC_PA_LB_PHY; 1995 } 1996 if(local_ability & BSDK_PHY84728_PA_AN) { 1997 ability->flags = SOC_PA_AUTONEG; 1998 } 1999 2000 return SOC_E_NONE; 2001 } 2002 2003 STATIC int 2004 _phy_84728_init_ucode_bcst(int unit, int port, int cmd) 2005 { 2006 uint16 data16; 2007 int j; 2008 uint16 num_words; 2009 uint8 *fw_ptr; 2010 int fw_length; 2011 phy_ctrl_t *pc; 2012 2013 pc = EXT_PHY_SW_STATE(unit, port); 2014 2015 if (cmd == PHYCTRL_UCODE_BCST_SETUP) { 2016 2017 LOG_INFO(BSL_LS_SOC_PHY, 2018 (BSL_META_U(unit, 2019 "PHY84740 BCST start: u=%d p=%d\n"), unit, port)); 2020 SOC_IF_ERROR_RETURN 2021 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc8fe, 0xffff)); 2022 return SOC_E_NONE; 2023 2024 } else if (cmd == PHYCTRL_UCODE_BCST_uC_SETUP) { 2025 LOG_INFO(BSL_LS_SOC_PHY, 2026 (BSL_META_U(unit, 2027 "PHY84740 BCST1: u=%d p=%d\n"), unit, port)); 2028 /* 0xc848[15]=0, MDIO downloading to RAM, 0xc848[14]=1, serial boot */ 2029 /* 0xc848[13]=0, SPI-ROM downloading not done, 0xc848[2]=0, spi port enable */ 2030 SOC_IF_ERROR_RETURN( 2031 BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc848, 2032 (0 << 15)|(1 << 14), 2033 (1 << 15)|(1 << 14)|((1 << 13) | (1 << 2)))); 2034 2035 /* apply bcst Reset to start download code from MDIO */ 2036 SOC_IF_ERROR_RETURN 2037 (BSDK_WR_PHY84728_LN_DEV1_PMD_CTRLr(pc, 0x8000)); 2038 return SOC_E_NONE; 2039 } else if (cmd == PHYCTRL_UCODE_BCST_ENABLE) { 2040 LOG_INFO(BSL_LS_SOC_PHY, 2041 (BSL_META_U(unit, 2042 "PHY84740 BCST2: u=%d p=%d\n"), unit, port)); 2043 /* reset clears bcst register */ 2044 /* restore bcst register after reset */ 2045 SOC_IF_ERROR_RETURN 2046 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc8fe, 0xffff)); 2047 return SOC_E_NONE; 2048 2049 } else if (cmd == PHYCTRL_UCODE_BCST_LOAD) { 2050 LOG_INFO(BSL_LS_SOC_PHY, 2051 (BSL_META_U(unit, 2052 "firmware_bcst,device name %s: u=%d p=%d\n"), 2053 pc->dev_name? pc->dev_name: "NULL", unit, port)); 2054 /* find the right firmware */ 2055 /* MDIO based firmware download to RAM */ 2056 if (BSDK_PHY84728_IS_84728(PHY84728_MAP(pc)->devid)) { 2057 fw_ptr = bcm84728_fw; 2058 fw_length = bcm84728_fw_length; 2059 } else { /* non-84728 device */ 2060 fw_ptr = bcm84748_fw; 2061 fw_length = bcm84748_fw_length; 2062 } 2063 2064 /* wait for 2ms for M8051 start and 5ms to initialize the RAM */ 2065 sal_usleep(10000); /* Wait for 10ms */ 2066 2067 /* Write Starting Address, where the Code will reside in SRAM */ 2068 data16 = 0x8000; 2069 SOC_IF_ERROR_RETURN 2070 (BSDK_WR_PHY84728_LN_DEV1_M8501_MSGINr(pc, data16)); 2071 2072 /* make sure address word is read by the micro */ 2073 sal_udelay(10); /* Wait for 10us */ 2074 2075 /* Write SPI SRAM Count Size */ 2076 data16 = (fw_length)/2; 2077 SOC_IF_ERROR_RETURN 2078 (BSDK_WR_PHY84728_LN_DEV1_M8501_MSGINr(pc, data16)); 2079 2080 /* make sure read by the micro */ 2081 sal_udelay(10); /* Wait for 10us */ 2082 2083 /* Fill in the SRAM */ 2084 num_words = (fw_length - 1); 2085 for (j = 0; j < num_words; j+=2) { 2086 /* Make sure the word is read by the Micro */ 2087 sal_udelay(10); 2088 data16 = (fw_ptr[j] << 8) | fw_ptr[j+1]; 2089 SOC_IF_ERROR_RETURN 2090 (BSDK_WR_PHY84728_LN_DEV1_M8501_MSGINr(pc, data16)); 2091 } 2092 return SOC_E_NONE; 2093 2094 } else if (cmd == PHYCTRL_UCODE_BCST_END) { 2095 LOG_INFO(BSL_LS_SOC_PHY, 2096 (BSL_META_U(unit, 2097 "PHY84740 BCST end: u=%d p=%d\n"), unit, port)); 2098 2099 /* make sure last code word is read by the micro */ 2100 sal_udelay(20); 2101 2102 /* first disable bcst mode */ 2103 SOC_IF_ERROR_RETURN 2104 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc8fe, 0)); 2105 2106 /* Read Hand-Shake message (Done) from Micro */ 2107 SOC_IF_ERROR_RETURN 2108 (BSDK_RD_PHY84728_LN_DEV1_M8501_MSGOUTr(pc, &data16)); 2109 if (data16 != 0x4321 ) { 2110 /* Download done message */ 2111 LOG_CLI((BSL_META_U(unit, 2112 "MDIO firmware download failed. Message: 0x%x\n"), 2113 data16)); 2114 return SOC_E_FAIL; 2115 } 2116 2117 /* Download done message */ 2118 LOG_INFO(BSL_LS_SOC_PHY, 2119 (BSL_META_U(unit, 2120 "u=%d p=%d MDIO firmware download done message: 0x%x\n"), 2121 unit, port,data16)); 2122 2123 /* Clear LASI status */ 2124 SOC_IF_ERROR_RETURN 2125 (BSDK_RD_PHY84728_LN_DEV1_RX_ALARMr(pc, &data16)); 2126 2127 /* Wait for LASI to be asserted when M8051 writes checksum to MSG_OUTr */ 2128 sal_udelay(100); /* Wait for 100 usecs */ 2129 2130 SOC_IF_ERROR_RETURN 2131 (BSDK_RD_PHY84728_LN_DEV1_M8501_MSGOUTr(pc, &data16)); 2132 2133 /* Need to check if checksum is correct */ 2134 SOC_IF_ERROR_RETURN 2135 (BSDK_RD_PHY84728_LN_DEV1_CHECKSUMr(pc, &data16)); 2136 2137 if (data16 != 0x600D) { 2138 /* Bad CHECKSUM */ 2139 LOG_CLI((BSL_META_U(unit, 2140 "firmware_bcst downlad failure: port %d " 2141 "Incorrect Checksum %x\n"), port, data16)); 2142 return SOC_E_FAIL; 2143 } 2144 2145 /* read Rev-ID */ 2146 SOC_IF_ERROR_RETURN 2147 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xCA1A, &data16)); 2148 LOG_ERROR(BSL_LS_SOC_PHY, 2149 (BSL_META_U(unit, 2150 "u=%d p=%d MDIO Firmware broadcast download revID: 0x%x\n"), 2151 unit, port,data16)); 2152 2153 return SOC_E_NONE; 2154 2155 } else { 2156 LOG_WARN(BSL_LS_SOC_PHY, 2157 (BSL_META_U(unit, 2158 "u=%d p=%d firmware_bcst: invalid cmd 0x%x\n"), 2159 unit, port,cmd)); 2160 } 2161 2162 return SOC_E_FAIL; 2163 } 2164 2165 2166 /* 2167 * Function: 2168 * phy_84728_firmware_set 2169 * Purpose: 2170 * program the given firmware into the SPI-ROM 2171 * Parameters: 2172 * unit - StrataSwitch unit #. 2173 * port - StrataSwitch port #. 2174 * offset - offset to the data stream 2175 * array - the given data 2176 * datalen- the data length 2177 * Returns: 2178 * SOC_E_NONE 2179 */ 2180 2181 STATIC int 2182 phy_84728_firmware_set(int unit, int port, int offset, uint8 *data, int len) 2183 { 2184 int rv; 2185 phy_ctrl_t *pc; 2186 2187 if (data == NULL) { 2188 return _phy_84728_init_ucode_bcst(unit, port, offset); 2189 } 2190 2191 pc = EXT_PHY_SW_STATE(unit, port); 2192 2193 rv = bsdk_phy84728_spi_firmware_update(pc, data, len); 2194 if (rv != SOC_E_NONE) { 2195 LOG_WARN(BSL_LS_SOC_PHY, 2196 (BSL_META_U(unit, 2197 "PHY84728 firmware upgrade possibly failed:" 2198 "u=%d p=%d\n"), unit, port)); 2199 return (SOC_E_FAIL); 2200 } 2201 LOG_INFO(BSL_LS_SOC_PHY, 2202 (BSL_META_U(unit, 2203 "PHY84728 firmware upgrade successful:" 2204 "u=%d p=%d\n"), unit, port)); 2205 2206 return SOC_E_NONE; 2207 } 2208 2209 /* 2210 * Function: 2211 * phy_84728_medium_status 2212 * Purpose: 2213 * Indicate the current active medium 2214 * Parameters: 2215 * unit - StrataSwitch unit #. 2216 * port - StrataSwitch port #. 2217 * medium - (OUT) One of: 2218 * SOC_PORT_MEDIUM_COPPER 2219 * SOC_PORT_MEDIUM_XAUI 2220 * Returns: 2221 * SOC_E_NONE 2222 */ 2223 2224 STATIC int 2225 phy_84728_medium_status(int unit, soc_port_t port, soc_port_medium_t *medium) 2226 { 2227 phy_ctrl_t *pc; 2228 2229 pc = EXT_PHY_SW_STATE(unit, port); 2230 2231 if (NXT_PC(pc)) { 2232 PHYDRV_CALL_ARG1(pc,PHY_MEDIUM_GET, medium); 2233 return SOC_E_NONE; 2234 } 2235 if (PHY_COPPER_MODE(unit, port)) { 2236 *medium = SOC_PORT_MEDIUM_COPPER; 2237 } else { 2238 *medium = SOC_PORT_MEDIUM_FIBER; 2239 } 2240 2241 2242 return SOC_E_NONE; 2243 } 2244 2245 2246 /* 2247 * Function: 2248 * phy_84728_control_set 2249 * Purpose: 2250 * Configure PHY device specific control fucntion. 2251 * Parameters: 2252 * unit - StrataSwitch unit #. 2253 * port - StrataSwitch port #. 2254 * type - Control to update 2255 * value - New setting for the control 2256 * Returns: 2257 * SOC_E_NONE 2258 */ 2259 STATIC int 2260 phy_84728_control_set(int unit, soc_port_t port, 2261 soc_phy_control_t type, uint32 value) 2262 { 2263 int rv; 2264 phy_ctrl_t *pc; 2265 uint16 regval = 0; 2266 2267 PHY_CONTROL_TYPE_CHECK(type); 2268 2269 pc = EXT_PHY_SW_STATE(unit, port); 2270 rv = SOC_E_UNAVAIL; 2271 2272 if (NXT_PC(pc)) { 2273 PHYDRV_CALL_ARG2(pc, PHY_CONTROL_SET, type, value); 2274 return SOC_E_NONE; 2275 } 2276 2277 switch(type) { 2278 case SOC_PHY_CONTROL_WAN: 2279 rv = _phy_84728_mode_set(unit, port, 2280 value ? WAN_MODE : LAN_MODE); 2281 break; 2282 2283 case SOC_PHY_CONTROL_EDC_MODE: 2284 rv = _phy_84728_control_edc_mode_set(unit,port,value); 2285 break; 2286 2287 case SOC_PHY_CONTROL_CLOCK_ENABLE: 2288 2289 if(value) { 2290 regval = (1 << 10); 2291 } 2292 SOC_IF_ERROR_RETURN 2293 (BSDK_PHY84728_REG_MOD(pc, 0x01,0x01,0xca23,regval,0x400)); 2294 2295 rv = SOC_E_NONE; 2296 break; 2297 2298 case SOC_PHY_CONTROL_CLOCK_FREQUENCY: 2299 2300 switch(value) 2301 { 2302 case 125000: /* for 125 MHz */ 2303 regval = 1; 2304 break; 2305 case 19531: /* for 19.53125 MHz */ 2306 regval = 2; 2307 break; 2308 case 156250: 2309 regval = 3; /* for 156.25 MHz */ 2310 break; 2311 default: 2312 return SOC_E_PARAM; 2313 break; 2314 } 2315 regval = (regval << 14); /* programming the frequency */ 2316 regval |= (1 << 13); 2317 2318 SOC_IF_ERROR_RETURN 2319 (BSDK_PHY84728_REG_MOD(pc, 0x01,0x01,0xcace,regval, 0xe000)); 2320 rv = SOC_E_NONE; 2321 break; 2322 case SOC_PHY_CONTROL_PARALLEL_DETECTION: 2323 rv = _phy_84728_control_pdet_set(unit, port, value); 2324 break; 2325 2326 default: 2327 break; 2328 } 2329 return rv; 2330 } 2331 2332 /* 2333 * Function: 2334 * phy_84728_control_get 2335 * Purpose: 2336 * Get current control settign of the PHY. 2337 * Parameters: 2338 * unit - StrataSwitch unit #. 2339 * port - StrataSwitch port #. 2340 * type - Control to update 2341 * value - (OUT)Current setting for the control 2342 * Returns: 2343 * SOC_E_NONE 2344 */ 2345 STATIC int 2346 phy_84728_control_get(int unit, soc_port_t port, 2347 soc_phy_control_t type, uint32 *value) 2348 { 2349 int rv; 2350 uint16 temp16; 2351 phy_ctrl_t *pc; 2352 2353 if (NULL == value) { 2354 return SOC_E_PARAM; 2355 } 2356 2357 PHY_CONTROL_TYPE_CHECK(type); 2358 2359 pc = EXT_PHY_SW_STATE(unit, port); 2360 rv = SOC_E_UNAVAIL; 2361 2362 if (NXT_PC(pc)) { 2363 PHYDRV_CALL_ARG2(pc, PHY_CONTROL_GET, type, value); 2364 return SOC_E_NONE; 2365 } 2366 2367 switch(type) { 2368 case SOC_PHY_CONTROL_WAN: 2369 *value = PHY_WAN_MODE(unit, port) ? 1 : 0; 2370 rv = SOC_E_NONE; 2371 break; 2372 2373 case SOC_PHY_CONTROL_EDC_MODE: 2374 rv = _phy_84728_control_edc_mode_get(unit,port,value); 2375 break; 2376 2377 case SOC_PHY_CONTROL_CLOCK_ENABLE: 2378 2379 { 2380 SOC_IF_ERROR_RETURN 2381 (BSDK_PHY84728_REG_RD(pc, 0x01,0x01,0xca23,&temp16)); 2382 *value = (temp16 & (0x1 << 10))? TRUE : FALSE; 2383 } 2384 rv = SOC_E_NONE; 2385 break; 2386 2387 case SOC_PHY_CONTROL_CLOCK_FREQUENCY: 2388 2389 2390 SOC_IF_ERROR_RETURN 2391 (BSDK_PHY84728_REG_RD(pc, 0x01,0x01,0xcace,&temp16)); 2392 2393 if(temp16 & (0x1 << 13)) 2394 { 2395 switch(temp16 >> 14) 2396 { 2397 case 1: /* for 125 MHz */ 2398 *value = 125000; 2399 break; 2400 case 2: /* for 19.53125 MHz */ 2401 *value = 19531; 2402 break; 2403 case 3: 2404 *value = 156250; /* for 156.25 MHz */ 2405 break; 2406 default: 2407 *value = 0; 2408 break; 2409 } 2410 if(*value) { 2411 rv = SOC_E_NONE; 2412 } else { 2413 rv = SOC_E_UNAVAIL; 2414 } 2415 } else { 2416 rv = SOC_E_DISABLED; 2417 } 2418 break; 2419 case SOC_PHY_CONTROL_PARALLEL_DETECTION: 2420 rv = _phy_84728_control_pdet_get(unit, port, value); 2421 break; 2422 2423 default: 2424 break; 2425 } 2426 return rv; 2427 } 2428 2429 /* 2430 * Function: 2431 * phy_84728_link_up 2432 * Purpose: 2433 * Link up handler 2434 * Parameters: 2435 * unit - StrataSwitch unit #. 2436 * port - StrataSwitch port #. 2437 * Returns: 2438 * SOC_E_NONE 2439 */ 2440 STATIC int 2441 phy_84728_link_up(int unit, soc_port_t port) 2442 { 2443 2444 /* After link up configure the system side to operate at 10G */ 2445 phy_ctrl_t *pc; 2446 bsdk_phy84728_intf_t line_mode; 2447 int speed; 2448 2449 pc = EXT_PHY_SW_STATE(unit, port); 2450 2451 SOC_IF_ERROR_RETURN 2452 (phy_84728_speed_get(unit, port, &speed)); 2453 2454 if (NXT_PC(pc)) { 2455 PHYDRV_CALL_NOARG(pc, PHY_LINKUP_EVT); 2456 /* PHYDRV_CALL_ARG1(pc,PHY_SPEED_GET, &speed); */ 2457 if (speed == 10000) { 2458 line_mode = BSDK_PHY84728_INTF_SFI; 2459 SOC_IF_ERROR_RETURN( 2460 bsdk_phy84728_sys_mode_set(pc, 0, 2461 BSDK_PHY84728_INTF_XAUI)); 2462 } else if (speed == 1000) { 2463 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_COPPER)) { 2464 line_mode = BSDK_PHY84728_INTF_SGMII; 2465 SOC_IF_ERROR_RETURN( 2466 bsdk_phy84728_sys_mode_set(pc, 0, 2467 BSDK_PHY84728_INTF_SGMII)); 2468 } else { 2469 line_mode = BSDK_PHY84728_INTF_1000X; 2470 SOC_IF_ERROR_RETURN( 2471 bsdk_phy84728_sys_mode_set(pc, 0, 2472 BSDK_PHY84728_INTF_1000X)); 2473 } 2474 } else { 2475 line_mode = BSDK_PHY84728_INTF_SGMII; 2476 SOC_IF_ERROR_RETURN( 2477 bsdk_phy84728_sys_mode_set(pc, 0, 2478 BSDK_PHY84728_INTF_SGMII)); 2479 } 2480 SOC_IF_ERROR_RETURN 2481 (bsdk_phy84728_line_mode_set(pc, 0, line_mode)); 2482 2483 SOC_IF_ERROR_RETURN 2484 (bsdk_phy84728_speed_set(pc, speed)); 2485 } 2486 2487 SOC_IF_ERROR_RETURN( 2488 bsdk_phy84728_line_intf_get(pc, 0, &line_mode)); 2489 2490 if (line_mode == BSDK_PHY84728_INTF_SGMII) { 2491 SOC_IF_ERROR_RETURN( 2492 _bsdk_phy84728_system_sgmii_sync(pc, 0)); 2493 SOC_IF_ERROR_RETURN 2494 (soc_phyctrl_notify(unit, port, phyEventInterface, SOC_PORT_IF_SGMII)); 2495 } 2496 #if 0 /* don't need to notify if speed is 10G */ 2497 else { 2498 SOC_IF_ERROR_RETURN 2499 (soc_phyctrl_notify(unit, port, phyEventInterface, SOC_PORT_IF_XAUI)); 2500 } 2501 #endif 2502 2503 if (PHY84728_MAP(pc)->link_down) { /* was link down */ 2504 if ( speed < 10000 ) { /* don't need to notify if speed is 10G */ 2505 SOC_IF_ERROR_RETURN 2506 (soc_phyctrl_notify(unit, port, phyEventSpeed, speed)); 2507 } 2508 PHY84728_MAP(pc)->link_down = 0; /* link is up now */ 2509 } 2510 2511 if ((line_mode == BSDK_PHY84728_INTF_SGMII) || (line_mode == BSDK_PHY84728_INTF_1000X)) { 2512 SOC_IF_ERROR_RETURN( 2513 bsdk_phy84728_lane_map(pc)); 2514 } 2515 2516 return SOC_E_NONE; 2517 } 2518 2519 /* 2520 * Function: 2521 * phy_84728_link_down 2522 * Purpose: 2523 * Link down handler 2524 * Parameters: 2525 * unit - StrataSwitch unit #. 2526 * port - StrataSwitch port #. 2527 * Returns: 2528 * SOC_E_NONE 2529 */ 2530 STATIC int 2531 phy_84728_link_down(int unit, soc_port_t port) 2532 { 2533 2534 /* After link up configure the system side to operate at 10G */ 2535 phy_ctrl_t *pc; 2536 2537 pc = EXT_PHY_SW_STATE(unit, port); 2538 2539 PHY84728_MAP(pc)->link_down = 1; 2540 return SOC_E_NONE; 2541 } 2542 2543 2544 /* 2545 * Function: 2546 * phy_84728_interface_get 2547 * Purpose: 2548 * Get interface on a given port. 2549 * Parameters: 2550 * unit - StrataSwitch unit #. 2551 * port - StrataSwitch port #. 2552 * pif - Interface. 2553 * Returns: 2554 * SOC_E_NONE 2555 */ 2556 STATIC int 2557 phy_84728_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 2558 { 2559 phy_ctrl_t *pc; 2560 bsdk_phy84728_intf_t line_mode; 2561 2562 pc = EXT_PHY_SW_STATE(unit, port); 2563 2564 SOC_IF_ERROR_RETURN( 2565 bsdk_phy84728_line_intf_get(pc, 0, &line_mode)); 2566 2567 if (line_mode == BSDK_PHY84728_INTF_SGMII) { 2568 *pif = SOC_PORT_IF_SGMII; 2569 } else { 2570 *pif = SOC_PORT_IF_XGMII; 2571 } 2572 2573 return SOC_E_NONE; 2574 } 2575 2576 /* 2577 * Function: 2578 * phy_84728_probe 2579 * Purpose: 2580 * Complement the generic phy probe routine to identify this phy when its 2581 * phy id0 and id1 is same as some other phy's. 2582 * Parameters: 2583 * unit - StrataSwitch unit #. 2584 * pc - phy ctrl descriptor. 2585 * Returns: 2586 * SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error> 2587 */ 2588 STATIC int 2589 phy_84728_probe(int unit, phy_ctrl_t *pc) 2590 { 2591 uint16 data1, data2; 2592 2593 if (READ_PHY84728_PMA_PMD_REG(unit, pc, 0xc802, &data1) < 0) { 2594 return SOC_E_NOT_FOUND; 2595 } 2596 2597 if (READ_PHY84728_PMA_PMD_REG(unit, pc, 0xc803, &data2) < 0) { 2598 return SOC_E_NOT_FOUND; 2599 } 2600 2601 if ((data2 & 0xf) == 0x8) { 2602 2603 switch (data1) { 2604 2605 case 0x4707: 2606 case 0x4073: 2607 case 0x4074: 2608 case 0x4728: 2609 case 0x4748: 2610 case 0x4727: 2611 case 0x4747: 2612 case 0x4722: 2613 case 0x4742: 2614 case 0x4762: 2615 case 0x4764: 2616 case 0x4042: 2617 case 0x4044: 2618 2619 pc->size = sizeof(phy84728_map_t); 2620 return SOC_E_NONE; 2621 } 2622 } 2623 2624 if ((data2 & 0xf) == 0x5) { 2625 2626 switch (data1) { 2627 2628 case 0x4942: 2629 2630 pc->size = sizeof(phy84728_map_t); 2631 return SOC_E_NONE; 2632 } 2633 } 2634 2635 return SOC_E_NOT_FOUND; 2636 } 2637 2638 /* 2639 * Function: 2640 * _phy84728_get_model_rev 2641 * Purpose: 2642 * Get OUI, Model and Revision of the PHY 2643 * Parameters: 2644 * phy_dev_addr - PHY Device Address 2645 * oui - (OUT) Organization Unique Identifier 2646 * model - (OUT)Device Model number` 2647 * rev - (OUT)Device Revision number 2648 * Notes: 2649 */ 2650 int 2651 _phy84728_get_model_rev(phy_ctrl_t *pc, 2652 int *oui, int *model, int *rev) 2653 { 2654 uint16 id0, id1; 2655 2656 SOC_IF_ERROR_RETURN 2657 (BSDK_RD_PHY84728_LN_DEV1_PMD_ID0r(pc, &id0)); 2658 2659 SOC_IF_ERROR_RETURN 2660 (BSDK_RD_PHY84728_LN_DEV1_PMD_ID1r(pc, &id1)); 2661 2662 *oui = BSDK_PHY84728_PHY_OUI(id0, id1); 2663 *model = BSDK_PHY84728_PHY_MODEL(id0, id1); 2664 *rev = BSDK_PHY84728_PHY_REV(id0, id1); 2665 2666 return SOC_E_NONE; 2667 } 2668 2669 2670 2671 /* 2672 * Function: 2673 * bsdk_phy84728_firmware_spi_download 2674 * Purpose: 2675 * Download firmware via SPI 2676 * - Check if firmware download is complete 2677 * - Check if the checksum is good 2678 * Parameters: 2679 * phy_id - PHY Device Address 2680 * Returns: 2681 */ 2682 /* STATIC int */ 2683 int 2684 bsdk_phy84728_firmware_spi_download(phy_ctrl_t *pc) 2685 { 2686 uint16 data = 0; 2687 int i; 2688 2689 /* 0xc848[15]=1, SPI-ROM downloading to RAM, 0xc848[14]=1, serial boot */ 2690 /* 0xc848[13]=0, SPI-ROM downloading not done, 0xc848[2]=0, spi port enable */ 2691 SOC_IF_ERROR_RETURN( 2692 BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc848, 2693 (1 << 15)|(1 << 14), 2694 ((1 << 15)|(1 << 14)|(1 << 13)|(1 << 2)))); 2695 2696 /* apply software reset to download code from SPI-ROM */ 2697 /* Reset the PHY **/ 2698 SOC_IF_ERROR_RETURN( 2699 BSDK_MOD_PHY84728_LN_DEV1_PMD_CTRLr(pc, 2700 BSDK_PHY84728_PMD_CTRL_RESET, BSDK_PHY84728_PMD_CTRL_RESET)); 2701 2702 for (i = 0; i < 5; i++) { 2703 sal_usleep(100000); 2704 SOC_IF_ERROR_RETURN( 2705 BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc848, &data)); 2706 if (data & 0x2000) { /* Check for download complete */ 2707 /* Need to check if checksum is correct */ 2708 SOC_IF_ERROR_RETURN( 2709 BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xca1c, &data)); 2710 if (data == 0x600D) { 2711 break; 2712 } 2713 } 2714 } 2715 if (i >= 5) { /* Bad CHECKSUM */ 2716 LOG_CLI((BSL_META_U(pc->unit, 2717 "SPI-Download Firmware download failure:" 2718 "Incorrect Checksum %x\n"), data)); 2719 return SOC_E_FAIL; 2720 } 2721 2722 SOC_IF_ERROR_RETURN( 2723 BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xca1a, &data)); 2724 2725 LOG_CLI((BSL_META_U(pc->unit, 2726 "BCM84728: u=%d p=%d: SPI-ROM download complete: " 2727 "Version: 0x%x\n"), 2728 pc->unit, pc->port, data)); 2729 2730 return SOC_E_NONE; 2731 } 2732 2733 /* 2734 * Function: 2735 * bsdk_phy84728_line_intf_get 2736 * Purpose: 2737 * Determine the Line side Interface 2738 * Parameters: 2739 * phy_id - PHY's device address 2740 * dev_port - Channel number 2741 * mode - (OUT) Line Port mode status 2742 * Returns: 2743 */ 2744 int 2745 bsdk_phy84728_line_intf_get(phy_ctrl_t *pc, int dev_port, 2746 bsdk_phy84728_intf_t *mode) 2747 { 2748 2749 phy84728_map_t *phy_info; 2750 2751 if (mode == NULL) { 2752 return SOC_E_PARAM; 2753 } 2754 2755 phy_info = PHY84728_MAP(pc); 2756 2757 *mode = phy_info->line_mode; 2758 return SOC_E_NONE; 2759 } 2760 2761 2762 2763 /* 2764 * Function: 2765 * bsdk_phy84728_line_mode_set 2766 * Purpose: 2767 * Set the Line side mode 2768 * Parameters: 2769 * phy_id - PHY's device address 2770 * dev_port - Channel number 2771 * mode - Desired mode (SGMII/1000x/SFI) 2772 * Returns: 2773 */ 2774 int 2775 bsdk_phy84728_line_mode_set(phy_ctrl_t *pc, int dev_port, 2776 bsdk_phy84728_intf_t mode) 2777 { 2778 2779 int rv = SOC_E_NONE; 2780 phy84728_map_t *phy_info; 2781 2782 phy_info = PHY84728_MAP(pc); 2783 2784 /* Disable Autodetect */ 2785 SOC_IF_ERROR_RETURN( 2786 BSDK_MOD_PHY84728_LN_DEV7_AN_BASE1000X_CTRL1r(pc, 0, 2787 BSDK_PHY84728_AN_BASE1000X_CTRL1_AUTODETECT_EN)); 2788 switch (mode) { 2789 2790 case BSDK_PHY84728_INTF_SGMII : 2791 2792 SOC_IF_ERROR_RETURN( 2793 BSDK_WR_PHY84728_LN_DEV7_AN_BASE1000X_CTRL1r(pc, BSDK_PHY84728_AN_BASE1000X_CTRL1_COMMA_DET_EN | 2794 BSDK_PHY84728_AN_BASE1000X_CTRL1_CRC_CHK_DIS | 2795 BSDK_PHY84728_AN_BASE1000X_CTRL1_SD_ENABLE)); 2796 SOC_IF_ERROR_RETURN( 2797 BSDK_WR_PHY84728_LN_DEV7_AN_MISC1r(pc, 0x6000)); 2798 SOC_IF_ERROR_RETURN( 2799 BSDK_MOD_PHY84728_LN_DEV7_AN_MSIC2r(pc, BSDK_PHY84728_AN_MISC2_RX_MII_GEN_SEL, 2800 BSDK_PHY84728_AN_MISC2_RX_MII_GEN_SEL | 2801 BSDK_PHY84728_AN_MISC2_PMA_PMD_FORCED_SPEED_ENC_EN)); 2802 SOC_IF_ERROR_RETURN( 2803 BSDK_WR_PHY84728_LN_DEV7_AN_SGMII_BASEPAGEr(pc, 0x0801)); 2804 SOC_IF_ERROR_RETURN( 2805 BSDK_WR_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, BSDK_PHY84728_AN_MII_CTRL_AE | 2806 BSDK_PHY84728_AN_MII_CTRL_FD | 2807 BSDK_PHY84728_AN_MII_CTRL_SS_1000)); 2808 break; 2809 2810 case BSDK_PHY84728_INTF_1000X : 2811 SOC_IF_ERROR_RETURN( 2812 BSDK_MOD_PHY84728_LN_DEV7_AN_BASE1000X_CTRL1r(pc, BSDK_PHY84728_AN_BASE1000X_CTRL1_FIBER_MODE, 2813 BSDK_PHY84728_AN_BASE1000X_CTRL1_FIBER_MODE)); 2814 /* Set PMA speed */ 2815 SOC_IF_ERROR_RETURN( 2816 BSDK_WR_PHY84728_LN_DEV1_PMD_CTRLr(pc, BSDK_PHY84728_PMD_CTRL_SS_1000)); 2817 break; 2818 2819 case BSDK_PHY84728_INTF_SFI : 2820 SOC_IF_ERROR_RETURN( 2821 BSDK_MOD_PHY84728_LN_DEV7_AN_BASE1000X_CTRL1r(pc, BSDK_PHY84728_AN_BASE1000X_CTRL1_FIBER_MODE, 2822 BSDK_PHY84728_AN_BASE1000X_CTRL1_FIBER_MODE)); 2823 /* Set PMA speed */ 2824 SOC_IF_ERROR_RETURN( 2825 BSDK_WR_PHY84728_LN_DEV1_PMD_CTRLr(pc, BSDK_PHY84728_PMD_CTRL_SS_10000)); 2826 break; 2827 2828 default : 2829 rv = SOC_E_PARAM; 2830 break; 2831 2832 } 2833 2834 if (SOC_SUCCESS(rv)) { 2835 phy_info->line_mode = mode; 2836 } 2837 return rv; 2838 } 2839 2840 2841 /* 2842 * Function: 2843 * bsdk_phy84728_sys_intf_get 2844 * Purpose: 2845 * Determine the System side Interface 2846 * Parameters: 2847 * phy_id - PHY's device address 2848 * dev_port - Channel number 2849 * mode - (OUT) System side mode status 2850 * Returns: 2851 */ 2852 int 2853 bsdk_phy84728_sys_intf_get(phy_ctrl_t *pc, int dev_port, 2854 bsdk_phy84728_intf_t *mode) 2855 { 2856 2857 phy84728_map_t *phy_info; 2858 2859 if (mode == NULL) { 2860 return SOC_E_PARAM; 2861 } 2862 2863 phy_info = PHY84728_MAP(pc); 2864 2865 /* System will always follow line side interface */ 2866 *mode = phy_info->line_mode; 2867 2868 return SOC_E_NONE; 2869 } 2870 2871 2872 2873 /* 2874 * Function: 2875 * bsdk_phy84728_sys_mode_set 2876 * Purpose: 2877 * Set the system side mode 2878 * Parameters: 2879 * phy_id - PHY's device address 2880 * dev_port - Channel number 2881 * mode - Desired mode (SGMII/1000x/XFI) 2882 * Returns: 2883 */ 2884 int 2885 bsdk_phy84728_sys_mode_set(phy_ctrl_t *pc, int dev_port, 2886 bsdk_phy84728_intf_t mode) 2887 { 2888 int rv = SOC_E_NONE; 2889 2890 /* Disable Autodetect */ 2891 SOC_IF_ERROR_RETURN( 2892 BSDK_MOD_PHY84728_SYS_DEV4_XGXS_BASE1000X_CTRL1r(pc, 0, 2893 BSDK_PHY84728_AN_BASE1000X_CTRL1_AUTODETECT_EN)); 2894 switch (mode) { 2895 case BSDK_PHY84728_INTF_SGMII : 2896 SOC_IF_ERROR_RETURN( 2897 BSDK_MOD_PHY84728_SYS_DEV4_XGXS_CTRLr(pc, 0x0000, BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ)); 2898 2899 SOC_IF_ERROR_RETURN( 2900 BSDK_WR_PHY84728_SYS_DEV4_XGXS_BASE1000X_CTRL1r(pc, BSDK_PHY84728_AN_BASE1000X_CTRL1_COMMA_DET_EN| 2901 BSDK_PHY84728_AN_BASE1000X_CTRL1_CRC_CHK_DIS | 2902 BSDK_PHY84728_AN_BASE1000X_CTRL1_SGMII_MASTER)); 2903 2904 SOC_IF_ERROR_RETURN( 2905 BSDK_WR_PHY84728_SYS_DEV4_XGXS_MISC1r(pc, 0x6000)); 2906 2907 SOC_IF_ERROR_RETURN( 2908 BSDK_MOD_PHY84728_SYS_DEV4_XGXS_MISC2r(pc, BSDK_PHY84728_AN_MISC2_RX_MII_GEN_SEL, 2909 BSDK_PHY84728_AN_MISC2_RX_MII_GEN_SEL | 2910 BSDK_PHY84728_AN_MISC2_PMA_PMD_FORCED_SPEED_ENC_EN)); 2911 2912 SOC_IF_ERROR_RETURN( 2913 BSDK_WR_PHY84728_SYS_DEV4_XGXS_SGMII_BASEPAGEr(pc, 0x0001)); 2914 2915 SOC_IF_ERROR_RETURN( 2916 BSDK_WR_PHY84728_SYS_DEV4_XGXS_MII_CTRLr(pc, BSDK_PHY84728_AN_MII_CTRL_FD | 2917 BSDK_PHY84728_AN_MII_CTRL_SS_1000)); 2918 2919 SOC_IF_ERROR_RETURN( 2920 BSDK_MOD_PHY84728_SYS_DEV4_XGXS_CTRLr(pc, BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ, 2921 BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ)); 2922 2923 break; 2924 2925 case BSDK_PHY84728_INTF_1000X : 2926 SOC_IF_ERROR_RETURN( 2927 BSDK_WR_PHY84728_SYS_DEV4_XGXS_BASE1000X_CTRL1r(pc, BSDK_PHY84728_AN_BASE1000X_CTRL1_COMMA_DET_EN| 2928 BSDK_PHY84728_AN_BASE1000X_CTRL1_CRC_CHK_DIS | 2929 BSDK_PHY84728_AN_BASE1000X_CTRL1_FIBER_MODE)); 2930 break; 2931 2932 case BSDK_PHY84728_INTF_XAUI : 2933 SOC_IF_ERROR_RETURN( 2934 BSDK_WR_PHY84728_SYS_DEV4_XGXS_BASE1000X_CTRL1r(pc, BSDK_PHY84728_AN_BASE1000X_CTRL1_COMMA_DET_EN| 2935 BSDK_PHY84728_AN_BASE1000X_CTRL1_CRC_CHK_DIS | 2936 BSDK_PHY84728_AN_BASE1000X_CTRL1_FIBER_MODE)); 2937 break; 2938 2939 default : 2940 rv = SOC_E_PARAM; 2941 break; 2942 } 2943 2944 return rv; 2945 } 2946 2947 2948 /* 2949 * Function: 2950 * bsdk_phy84728_no_reset_setup 2951 * Purpose: 2952 * Initialize the PHY without reset. 2953 * Parameters: 2954 * phy_dev_addr - PHY Device Address 2955 * line_mode - Line side Mode (SGMII/1000X/SFI). 2956 * fcmap_enable - Fibre Channel enabled or disabled. 2957 * Notes: 2958 */ 2959 int 2960 bsdk_phy84728_no_reset_setup(phy_ctrl_t *pc, int line_mode, 2961 int phy_ext_boot) 2962 { 2963 if ((line_mode != BSDK_PHY84728_INTF_SGMII) && 2964 (line_mode != BSDK_PHY84728_INTF_1000X) && 2965 (line_mode != BSDK_PHY84728_INTF_SFI)) { 2966 return SOC_E_CONFIG; 2967 } 2968 2969 /* Enable Power - PMA/PMD, PCS, AN */ 2970 SOC_IF_ERROR_RETURN( 2971 BSDK_MOD_PHY84728_LN_DEV1_PMD_CTRLr(pc, 0, 2972 BSDK_PHY84728_PMD_CTRL_PD)); 2973 SOC_IF_ERROR_RETURN( 2974 BSDK_MOD_PHY84728_LN_DEV3_PCS_CTRLr(pc, 0, 2975 BSDK_PHY84728_PCS_PCS_CTRL_PD)); 2976 SOC_IF_ERROR_RETURN( 2977 BSDK_MOD_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, 0, 2978 BSDK_PHY84728_AN_MII_CTRL_PD)); 2979 if (phy_ext_boot) { 2980 /* Download firmware if via SPI */ 2981 SOC_IF_ERROR_RETURN(bsdk_phy84728_firmware_spi_download(pc)); 2982 } else if (!(pc->flags & PHYCTRL_MDIO_BCST)) { 2983 /* MDIO based firmware download to RAM */ 2984 if (BSDK_PHY84728_IS_84728(PHY84728_MAP(pc)->devid)) { 2985 SOC_IF_ERROR_RETURN( 2986 bsdk_phy84728_mdio_firmware_download(pc, 2987 bcm84728_fw, bcm84728_fw_length)); 2988 } else { /* non-84728 device */ 2989 SOC_IF_ERROR_RETURN( 2990 bsdk_phy84728_mdio_firmware_download(pc, 2991 bcm84748_fw, bcm84748_fw_length)); 2992 } 2993 } 2994 2995 /* Set Line mode */ 2996 SOC_IF_ERROR_RETURN( 2997 bsdk_phy84728_line_mode_set(pc, 0, line_mode)); 2998 2999 /* System side mode */ 3000 if (line_mode == BSDK_PHY84728_INTF_SFI) { 3001 SOC_IF_ERROR_RETURN( 3002 bsdk_phy84728_sys_mode_set(pc, 0, 3003 BSDK_PHY84728_INTF_XAUI)); 3004 SOC_IF_ERROR_RETURN( 3005 bsdk_phy84728_speed_set(pc, 10000)); 3006 } else if (line_mode == BSDK_PHY84728_INTF_1000X) { 3007 SOC_IF_ERROR_RETURN( 3008 bsdk_phy84728_sys_mode_set(pc, 0, 3009 BSDK_PHY84728_INTF_1000X)); 3010 /* Force Speed to 1G */ 3011 SOC_IF_ERROR_RETURN( 3012 bsdk_phy84728_speed_set(pc, 1000)); 3013 } else { /* SGMII MODE */ 3014 SOC_IF_ERROR_RETURN( 3015 bsdk_phy84728_sys_mode_set(pc, 0, 3016 BSDK_PHY84728_INTF_SGMII)); 3017 } 3018 3019 return SOC_E_NONE; 3020 } 3021 3022 /* 3023 * Function: 3024 * bsdk_phy84728_reset 3025 * Purpose: 3026 * Reset the PHY. 3027 * Parameters: 3028 * phy_id - PHY Device Address of the PHY to reset 3029 */ 3030 int 3031 bsdk_phy84728_reset(phy_ctrl_t *pc) 3032 { 3033 int wan_mode; 3034 uint16 ctrl, tmp; 3035 3036 3037 /* Reset the PHY **/ 3038 SOC_IF_ERROR_RETURN( 3039 BSDK_RD_PHY84728_LN_DEV1_PMD_CTRLr(pc, &ctrl)); 3040 3041 SOC_IF_ERROR_RETURN( 3042 BSDK_WR_PHY84728_LN_DEV1_PMD_CTRLr(pc, 3043 (ctrl | BSDK_PHY84728_PMD_CTRL_RESET))); 3044 3045 wan_mode = soc_property_port_get(pc->unit, pc->port, spn_PHY_WAN_MODE, FALSE); 3046 3047 if (wan_mode) { 3048 SOC_IF_ERROR_RETURN( 3049 BSDK_MOD_PHY84728_WIS_CTRLr(pc, 3050 BSDK_PHY84728_WIS_CTRL_RESET, 3051 BSDK_PHY84728_WIS_CTRL_RESET)); 3052 } 3053 3054 /* Needs minimum of 5us to complete the reset */ 3055 sal_usleep(30); 3056 3057 SOC_IF_ERROR_RETURN( 3058 BSDK_RD_PHY84728_LN_DEV1_PMD_CTRLr(pc, &tmp)); 3059 3060 if ((tmp & BSDK_PHY84728_PMD_CTRL_RESET) != 0) { 3061 SOC_IF_ERROR_RETURN 3062 (BSDK_WR_PHY84728_LN_DEV1_PMD_CTRLr(pc, ctrl)); 3063 return SOC_E_FAIL; 3064 } 3065 3066 if (wan_mode) { 3067 SOC_IF_ERROR_RETURN( 3068 BSDK_MOD_PHY84728_WIS_CTRLr(pc, 3069 0, 3070 BSDK_PHY84728_WIS_CTRL_RESET)); 3071 } 3072 3073 return SOC_E_NONE; 3074 } 3075 /* 3076 * Function: 3077 * bsdk_phy84728_lane_map 3078 * Purpose: 3079 * To set the PHY's lane map 3080 * Parameters: 3081 * phy_id - PHY's device address 3082 * Returns: 3083 */ 3084 int 3085 bsdk_phy84728_lane_map(phy_ctrl_t *pc) 3086 { 3087 uint32 phy_sys_xaui_tx_lane_map, phy_sys_xaui_rx_lane_map; 3088 uint16 temp; 3089 3090 phy_sys_xaui_tx_lane_map = PHY84728_MAP(pc)->phy_sys_xaui_tx_lane_map ; 3091 3092 if (phy_sys_xaui_tx_lane_map) { 3093 LOG_INFO(BSL_LS_SOC_PHY, 3094 (BSL_META_U(pc->unit, 3095 "phy_sys_xaui_tx_lane_map: u=%d p=%d val=0x%x\n"), 3096 pc->unit, pc->port, phy_sys_xaui_tx_lane_map)); 3097 temp = ((phy_sys_xaui_tx_lane_map & (0x3<<12)) >> 6) | 3098 ((phy_sys_xaui_tx_lane_map & (0x3<<8)) >> 4) | 3099 ((phy_sys_xaui_tx_lane_map & (0x3<<4)) >> 2) | 3100 (phy_sys_xaui_tx_lane_map & 0x3) | 0x0100; 3101 SOC_IF_ERROR_RETURN( 3102 BSDK_PHY84728_REG_MOD(pc, 0x00, 0x0004, 0x8169, temp, 0x01ff)); 3103 } 3104 3105 phy_sys_xaui_rx_lane_map = PHY84728_MAP(pc)->phy_sys_xaui_rx_lane_map ; 3106 3107 if (phy_sys_xaui_rx_lane_map) { 3108 LOG_INFO(BSL_LS_SOC_PHY, 3109 (BSL_META_U(pc->unit, 3110 "phy_sys_xaui_rx_lane_map: u=%d p=%d val=0x%x\n"), 3111 pc->unit, pc->port, phy_sys_xaui_rx_lane_map)); 3112 temp = ((phy_sys_xaui_rx_lane_map & (0x3<<12)) >> 6) | 3113 ((phy_sys_xaui_rx_lane_map & (0x3<<8)) >> 4) | 3114 ((phy_sys_xaui_rx_lane_map & (0x3<<4)) >> 2) | 3115 (phy_sys_xaui_rx_lane_map & 0x3) | 0x0100; 3116 SOC_IF_ERROR_RETURN( 3117 BSDK_PHY84728_REG_MOD(pc, 0x00, 0x0004, 0x816b, temp, 0x01ff)); 3118 } 3119 3120 return SOC_E_NONE; 3121 } 3122 3123 3124 /* 3125 * Function: 3126 * bsdk_phy84728_speed_set 3127 * Purpose: 3128 * To set the PHY's speed 3129 * Parameters: 3130 * phy_id - PHY's device address 3131 * speed - Speed to set 3132 * 10 = 10Mbps 3133 * 100 = 100Mbps 3134 * 1000 = 1000Mbps 3135 * Returns: 3136 */ 3137 int 3138 bsdk_phy84728_speed_set(phy_ctrl_t *pc, int speed) 3139 { 3140 int value = 0; 3141 bsdk_phy84728_intf_t line_mode; 3142 3143 if ((speed != 10) && (speed != 100) && 3144 (speed != 1000) && (speed != 10000)) { 3145 return SOC_E_NONE; 3146 } 3147 3148 SOC_IF_ERROR_RETURN( 3149 bsdk_phy84728_line_intf_get(pc, 0, &line_mode)); 3150 3151 switch (line_mode) { 3152 case BSDK_PHY84728_INTF_SFI: 3153 case BSDK_PHY84728_INTF_1000X: 3154 /* Disable Clause 37 Autoneg */ 3155 SOC_IF_ERROR_RETURN( 3156 BSDK_MOD_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, 0x0000, 3157 BSDK_PHY84728_AN_MII_CTRL_AE)); 3158 SOC_IF_ERROR_RETURN( 3159 BSDK_MOD_PHY84728_LN_DEV7_AN_BASE1000X_CTRL1r(pc, BSDK_PHY84728_AN_BASE1000X_CTRL1_FIBER_MODE, 3160 BSDK_PHY84728_AN_BASE1000X_CTRL1_FIBER_MODE)); 3161 SOC_IF_ERROR_RETURN( 3162 BSDK_MOD_PHY84728_LN_DEV7_AN_MSIC2r(pc, BSDK_PHY84728_AN_MISC2_RX_MII_GEN_SEL | 3163 BSDK_PHY84728_AN_MISC2_PMA_PMD_FORCED_SPEED_ENC_EN, 3164 BSDK_PHY84728_AN_MISC2_RX_MII_GEN_SEL | 3165 BSDK_PHY84728_AN_MISC2_PMA_PMD_FORCED_SPEED_ENC_EN)); 3166 if (speed == 10000) { 3167 3168 /* Set Line mode */ 3169 SOC_IF_ERROR_RETURN( 3170 bsdk_phy84728_line_mode_set(pc, 0, 3171 BSDK_PHY84728_INTF_SFI)); 3172 3173 /* Set System side to match Line side */ 3174 SOC_IF_ERROR_RETURN( 3175 bsdk_phy84728_sys_mode_set(pc, 0, 3176 BSDK_PHY84728_INTF_XAUI)); 3177 /* Force Speed in PMD */ 3178 SOC_IF_ERROR_RETURN( 3179 BSDK_MOD_PHY84728_LN_DEV1_PMD_CTRLr(pc, 3180 BSDK_PHY84728_PMD_CTRL_SS_10000, 3181 BSDK_PHY84728_PMD_CTRL_10GSS_MASK)); 3182 /* Select 10G-LRM PMA */ 3183 SOC_IF_ERROR_RETURN( 3184 BSDK_MOD_PHY84728_LN_DEV1_PMD_CTRL2r(pc, 3185 BSDK_PHY84728_PMD_CTRL2_PMA_10GLRMPMD_TYPE, 3186 BSDK_PHY84728_PMD_CTRL2_PMA_SELECT_MASK)); 3187 3188 } else if (speed == 1000) { 3189 3190 /* Set Line mode */ 3191 SOC_IF_ERROR_RETURN( 3192 bsdk_phy84728_line_mode_set(pc, 0, 3193 BSDK_PHY84728_INTF_1000X)); 3194 /* Set System side to match Line side */ 3195 SOC_IF_ERROR_RETURN( 3196 bsdk_phy84728_sys_mode_set(pc, 0, 3197 BSDK_PHY84728_INTF_1000X)); 3198 /* Force Speed in PMD */ 3199 SOC_IF_ERROR_RETURN( 3200 BSDK_MOD_PHY84728_LN_DEV1_PMD_CTRLr(pc, 3201 BSDK_PHY84728_PMD_CTRL_SS_1000, 3202 BSDK_PHY84728_PMD_CTRL_10GSS_MASK)); 3203 } else { 3204 return SOC_E_CONFIG; 3205 } 3206 break; 3207 3208 case BSDK_PHY84728_INTF_SGMII: 3209 if (speed > 1000) { 3210 return SOC_E_CONFIG; 3211 } 3212 /* Disable Clause 37 Autoneg */ 3213 SOC_IF_ERROR_RETURN( 3214 BSDK_MOD_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, 0x0000, 3215 0x1000)); 3216 if (speed == 1000) { 3217 value = BSDK_PHY84728_PMD_CTRL_SS_1000; 3218 } 3219 if (speed == 100) { 3220 value = BSDK_PHY84728_PMD_CTRL_SS_100; 3221 } 3222 if (speed == 10) { 3223 value = BSDK_PHY84728_PMD_CTRL_SS_10; 3224 } 3225 SOC_IF_ERROR_RETURN( 3226 BSDK_MOD_PHY84728_LN_DEV7_XGXS_CTRLr(pc, 0x0000, BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ)); 3227 3228 SOC_IF_ERROR_RETURN( 3229 BSDK_MOD_PHY84728_LN_DEV7_AN_MII_CTRLr(pc, value, 3230 BSDK_PHY84728_AN_MII_CTRL_SS_MASK | BSDK_PHY84728_AN_MII_CTRL_AE)); 3231 3232 /* Force Speed in PMD */ 3233 SOC_IF_ERROR_RETURN( 3234 BSDK_MOD_PHY84728_LN_DEV1_PMD_CTRLr(pc, 3235 value, 3236 BSDK_PHY84728_PMD_CTRL_10GSS_MASK)); 3237 SOC_IF_ERROR_RETURN( 3238 BSDK_MOD_PHY84728_LN_DEV7_XGXS_CTRLr(pc, BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ, 3239 BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ)); 3240 break; 3241 3242 default: 3243 return SOC_E_CONFIG; 3244 } 3245 3246 /* Enable Squelch */ 3247 SOC_IF_ERROR_RETURN(_phy_84728_squelch_enable(pc->unit, pc->port, TRUE)); 3248 3249 return SOC_E_NONE; 3250 } 3251 3252 /* 3253 * Function: 3254 * phy_84728_mdix_set 3255 * Description: 3256 * Set the Auto-MDIX mode of a port/PHY 3257 * Parameters: 3258 * unit - Device number 3259 * port - Port number 3260 * mode - One of: 3261 * SOC_PORT_MDIX_AUTO 3262 * Enable auto-MDIX when autonegotiation is enabled 3263 * SOC_PORT_MDIX_FORCE_AUTO 3264 * Enable auto-MDIX always 3265 * SOC_PORT_MDIX_NORMAL 3266 * Disable auto-MDIX 3267 * SOC_PORT_MDIX_XOVER 3268 * Disable auto-MDIX, and swap cable pairs 3269 * Return Value: 3270 * SOC_E_XXX 3271 */ 3272 STATIC int 3273 phy_84728_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode) 3274 { 3275 phy_ctrl_t *pc; 3276 3277 pc = EXT_PHY_SW_STATE(unit, port); 3278 3279 if (PHY_COPPER_MODE(unit, port) && NXT_PC(pc)) { 3280 PHYDRV_CALL_ARG1(pc, PHY_MDIX_SET, mode); 3281 return SOC_E_NONE; 3282 } 3283 SOC_IF_ERROR_RETURN( 3284 phy_null_mdix_set(unit, port, mode)); 3285 3286 return SOC_E_NONE; 3287 3288 } 3289 3290 /* 3291 * Function: 3292 * phy_84728_mdix_get 3293 * Description: 3294 * Get the Auto-MDIX mode of a port/PHY 3295 * Parameters: 3296 * unit - Device number 3297 * port - Port number 3298 * mode - (Out) One of: 3299 * SOC_PORT_MDIX_AUTO 3300 * Enable auto-MDIX when autonegotiation is enabled 3301 * SOC_PORT_MDIX_FORCE_AUTO 3302 * Enable auto-MDIX always 3303 * SOC_PORT_MDIX_NORMAL 3304 * Disable auto-MDIX 3305 * SOC_PORT_MDIX_XOVER 3306 * Disable auto-MDIX, and swap cable pairs 3307 * Return Value: 3308 * SOC_E_XXX 3309 */ 3310 STATIC int 3311 phy_84728_mdix_get(int unit, soc_port_t port, soc_port_mdix_t *mode) 3312 { 3313 phy_ctrl_t *pc; 3314 3315 pc = EXT_PHY_SW_STATE(unit, port); 3316 3317 if (PHY_COPPER_MODE(unit, port) && NXT_PC(pc)) { 3318 PHYDRV_CALL_ARG1(pc, PHY_MDIX_GET, mode); 3319 return SOC_E_NONE; 3320 } 3321 SOC_IF_ERROR_RETURN( 3322 phy_null_mdix_get(unit, port, mode)); 3323 3324 return SOC_E_NONE; 3325 } 3326 3327 /* 3328 * Function: 3329 * phy_84728_mdix_status_get 3330 * Description: 3331 * Get the current MDIX status on a port/PHY 3332 * Parameters: 3333 * unit - Device number 3334 * port - Port number 3335 * status - (OUT) One of: 3336 * SOC_PORT_MDIX_STATUS_NORMAL 3337 * Straight connection 3338 * SOC_PORT_MDIX_STATUS_XOVER 3339 * Crossover has been performed 3340 * Return Value: 3341 * SOC_E_XXX 3342 */ 3343 STATIC int 3344 phy_84728_mdix_status_get(int unit, soc_port_t port, 3345 soc_port_mdix_status_t *status) 3346 { 3347 phy_ctrl_t *pc; 3348 3349 pc = EXT_PHY_SW_STATE(unit, port); 3350 3351 if (PHY_COPPER_MODE(unit, port) && NXT_PC(pc)) { 3352 PHYDRV_CALL_ARG1(pc, PHY_MDIX_STATUS_GET, status); 3353 return SOC_E_NONE; 3354 } 3355 SOC_IF_ERROR_RETURN( 3356 phy_null_mdix_status_get(unit, port, status)); 3357 3358 return SOC_E_NONE; 3359 } 3360 3361 /* 3362 * Function: 3363 * phy_84728_master_set 3364 * Purpose: 3365 * Set the master mode for the PHY. 3366 * Parameters: 3367 * unit - StrataSwitch unit #. 3368 * port - StrataSwitch port #. 3369 * master - SOC_PORT_MS_* 3370 * Returns: 3371 * SOC_E_XXX 3372 * Notes: 3373 * No synchronization performed at this level. Autonegotiation is 3374 * not manipulated. 3375 */ 3376 3377 STATIC int 3378 phy_84728_master_set(int unit, soc_port_t port, int master) 3379 { 3380 phy_ctrl_t *pc; 3381 3382 pc = EXT_PHY_SW_STATE(unit, port); 3383 3384 if (PHY_COPPER_MODE(unit, port) && NXT_PC(pc)) { 3385 PHYDRV_CALL_ARG1(pc, PHY_MASTER_SET, master); 3386 return SOC_E_NONE; 3387 } 3388 SOC_IF_ERROR_RETURN( 3389 phy_null_set(unit, port, master)); 3390 3391 return SOC_E_NONE; 3392 } 3393 3394 /* 3395 * Function: 3396 * phy_84728_master_get 3397 * Purpose: 3398 * Get the master mode for the PHY. If mode is forced, then 3399 * forced mode is returned; otherwise operating mode is returned. 3400 * Parameters: 3401 * unit - StrataSwitch unit #. 3402 * port - StrataSwitch port #. 3403 * master - (OUT) SOC_PORT_MS_* 3404 * Returns: 3405 * SOC_E_XXX 3406 * Notes: 3407 * No synchronization performed at this level. Autonegotiation is 3408 * not manipulated. 3409 */ 3410 3411 STATIC int 3412 phy_84728_master_get(int unit, soc_port_t port, int *master) 3413 { 3414 phy_ctrl_t *pc; 3415 3416 pc = EXT_PHY_SW_STATE(unit, port); 3417 3418 if (PHY_COPPER_MODE(unit, port) && NXT_PC(pc)) { 3419 PHYDRV_CALL_ARG1(pc, PHY_MASTER_GET, master); 3420 return SOC_E_NONE; 3421 } 3422 SOC_IF_ERROR_RETURN( 3423 phy_null_zero_get(unit, port, master)); 3424 3425 return SOC_E_NONE; 3426 } 3427 3428 /* 3429 * Function: 3430 * bsdk_phy84728_link_get 3431 * Purpose: 3432 * Determine the current link up/down status for a 84728 device. 3433 * Parameters: 3434 * phy_id - PHY Device Address 3435 * link - (OUT) 3436 * 1 = Indicates Link is established 3437 * 0 = No Link. 3438 * Returns: 3439 */ 3440 int 3441 bsdk_phy84728_link_get(phy_ctrl_t *pc, int *link) 3442 { 3443 3444 uint16 data = 0, pma_mii_stat = 0, pcs_mii_stat = 0; 3445 int an, an_done; 3446 bsdk_phy84728_intf_t line_mode; 3447 3448 *link = 0; 3449 SOC_IF_ERROR_RETURN( 3450 phy_84728_an_get(pc->unit, pc->port, &an, &an_done)); 3451 3452 /* Firmware issue: need to comment out as workaround */ 3453 #if 0 3454 if (an && (an_done == 0)) { 3455 /* Auto neg in progess, return no link */ 3456 *link = 0; 3457 return SOC_E_NONE; 3458 } 3459 #endif 3460 3461 3462 SOC_IF_ERROR_RETURN( 3463 bsdk_phy84728_line_intf_get(pc, 0, &line_mode)); 3464 3465 switch (line_mode) { 3466 case BSDK_PHY84728_INTF_SFI: 3467 3468 SOC_IF_ERROR_RETURN( 3469 BSDK_RD_PHY84728_LN_DEV1_PMD_STATr(pc, &pma_mii_stat)); 3470 3471 SOC_IF_ERROR_RETURN( 3472 BSDK_RD_PHY84728_LN_DEV3_PCS_STATr(pc, &pcs_mii_stat)); 3473 3474 if (pma_mii_stat == 0xffff || pcs_mii_stat == 0xffff) { 3475 *link = 0; 3476 break; 3477 } 3478 3479 *link = pma_mii_stat & pcs_mii_stat & BSDK_PHY84728_PMD_STAT_RX_LINK_STATUS; 3480 3481 break; 3482 3483 case BSDK_PHY84728_INTF_1000X: 3484 case BSDK_PHY84728_INTF_SGMII: 3485 SOC_IF_ERROR_RETURN( 3486 BSDK_RD_PHY84728_LN_DEV7_AN_MII_STATr(pc, &data)); 3487 3488 if (data == 0xffff) { 3489 *link = 0; 3490 break; 3491 } 3492 3493 *link = data & BSDK_PHY84728_AN_MII_STAT_LINK_STATUS; 3494 break; 3495 3496 default: 3497 break; 3498 } 3499 3500 if (*link == 0) { 3501 if (line_mode != BSDK_PHY84728_INTF_SGMII && an && an_done) { 3502 SOC_IF_ERROR_RETURN( 3503 bsdk_phy84728_line_mode_set(pc, 0, BSDK_PHY84728_INTF_1000X)); 3504 } 3505 } 3506 3507 return SOC_E_NONE; 3508 } 3509 3510 3511 /* 3512 * Function: 3513 * bsdk_phy84728_ability_advert_set 3514 * Purpose: 3515 * Set the current advertisement for auto-negotiation. 3516 * Parameters: 3517 * phy_id - PHY Device Address 3518 * ability - Ability indicating supported options/speeds. 3519 * For Speed & Duplex: 3520 * BSDK_PM_10MB_HD = 10Mb, Half Duplex 3521 * BSDK_PM_10MB_FD = 10Mb, Full Duplex 3522 * BSDK_PM_100MB_HD = 100Mb, Half Duplex 3523 * BSDK_PM_100MB_FD = 100Mb, Full Duplex 3524 * BSDK_PM_1000MB_HD = 1000Mb, Half Duplex 3525 * BSDK_PM_1000MB_FD = 1000Mb, Full Duplex 3526 * BSDK_PM_PAUSE_TX = TX Pause 3527 * BSDK_PM_PAUSE_RX = RX Pause 3528 * BSDK_PM_PAUSE_ASYMM = Asymmetric Pause 3529 * Returns: 3530 */ 3531 3532 int 3533 bsdk_phy84728_ability_advert_set(phy_ctrl_t *pc, 3534 bsdk_phy84728_port_ability_t ability) 3535 { 3536 uint16 data = 0; 3537 bsdk_phy84728_intf_t line_mode; 3538 3539 SOC_IF_ERROR_RETURN( 3540 bsdk_phy84728_line_intf_get(pc, 0, &line_mode)); 3541 3542 if (line_mode == BSDK_PHY84728_INTF_1000X) { 3543 /* Always advertise 1000X full duplex */ 3544 data = BSDK_PHY84728_DEV7_1000X_ANA_C37_FD; 3545 if ((ability & BSDK_PHY84728_PA_PAUSE) == 3546 BSDK_PHY84728_PA_PAUSE) { 3547 data |= BSDK_PHY84728_DEV7_1000X_ANA_C37_PAUSE; 3548 } else { 3549 if (ability & BSDK_PHY84728_PA_PAUSE_TX) { 3550 data |= BSDK_PHY84728_DEV7_1000X_ANA_C37_ASYM_PAUSE; 3551 } else { 3552 if (ability & BSDK_PHY84728_PA_PAUSE_RX) { 3553 data |= BSDK_PHY84728_DEV7_1000X_ANA_C37_ASYM_PAUSE; 3554 data |= BSDK_PHY84728_DEV7_1000X_ANA_C37_PAUSE; 3555 } 3556 } 3557 } 3558 SOC_IF_ERROR_RETURN( 3559 BSDK_WR_PHY84728_LN_DEV7_AN_ANAr(pc, data)); 3560 3561 } 3562 if (line_mode == BSDK_PHY84728_INTF_SGMII) { 3563 3564 3565 } else { 3566 /* No Autoneg in SFI mode */ 3567 /* return SOC_E_UNAVAIL; */ 3568 } 3569 return SOC_E_NONE; 3570 } 3571 3572 3573 /* 3574 * Function: 3575 * bsdk_phy84728_ability_advert_get 3576 * Purpose: 3577 * Get the current advertisement for auto-negotiation. 3578 * Parameters: 3579 * phy_id - PHY Device Address 3580 * ability - (OUT) Port ability mask indicating supported options/speeds. 3581 * For Speed & Duplex: 3582 * BSDK_PM_10MB_HD = 10Mb, Half Duplex 3583 * BSDK_PM_10MB_FD = 10Mb, Full Duplex 3584 * BSDK_PM_100MB_HD = 100Mb, Half Duplex 3585 * BSDK_PM_100MB_FD = 100Mb, Full Duplex 3586 * BSDK_PM_1000MB_HD = 1000Mb, Half Duplex 3587 * BSDK_PM_1000MB_FD = 1000Mb, Full Duplex 3588 * BSDK_PM_PAUSE_TX = TX Pause 3589 * BSDK_PM_PAUSE_RX = RX Pause 3590 * BSDK_PM_PAUSE_ASYMM = Asymmetric Pause 3591 * Returns: 3592 */ 3593 3594 int 3595 bsdk_phy84728_ability_advert_get(phy_ctrl_t *pc, 3596 bsdk_phy84728_port_ability_t *ability) 3597 { 3598 uint16 data = 0; 3599 bsdk_phy84728_intf_t line_mode; 3600 3601 if (ability == NULL) { 3602 return SOC_E_PARAM; 3603 } 3604 3605 SOC_IF_ERROR_RETURN( 3606 bsdk_phy84728_line_intf_get(pc, 0, &line_mode)); 3607 3608 if (line_mode == BSDK_PHY84728_INTF_1000X) { 3609 SOC_IF_ERROR_RETURN( 3610 BSDK_RD_PHY84728_LN_DEV7_AN_ANAr(pc, &data)); 3611 3612 *ability |= (data & BSDK_PHY84728_DEV7_1000X_ANA_C37_FD) ? 3613 BSDK_PHY84728_PA_1000MB_FD : 0; 3614 *ability |= (data & BSDK_PHY84728_DEV7_1000X_ANA_C37_HD) ? 3615 BSDK_PHY84728_PA_1000MB_HD : 0; 3616 switch (data & (BSDK_PHY84728_DEV7_1000X_ANA_C37_PAUSE | 3617 BSDK_PHY84728_DEV7_1000X_ANA_C37_ASYM_PAUSE)) { 3618 case BSDK_PHY84728_DEV7_1000X_ANA_C37_PAUSE: 3619 *ability |= BSDK_PHY84728_PA_PAUSE; 3620 break; 3621 case BSDK_PHY84728_DEV7_1000X_ANA_C37_ASYM_PAUSE: 3622 *ability |= BSDK_PHY84728_PA_PAUSE_TX; 3623 break; 3624 case (BSDK_PHY84728_DEV7_1000X_ANA_C37_PAUSE | 3625 BSDK_PHY84728_DEV7_1000X_ANA_C37_ASYM_PAUSE): 3626 *ability |= BSDK_PHY84728_PA_PAUSE_RX; 3627 break; 3628 } 3629 } else { 3630 if (line_mode == BSDK_PHY84728_INTF_SGMII) { 3631 *ability = BSDK_PHY84728_PA_SPEED_ALL | 3632 BSDK_PHY84728_PA_AN | 3633 BSDK_PHY84728_PA_PAUSE | 3634 BSDK_PHY84728_PA_PAUSE_ASYMM; 3635 3636 } else { 3637 /* No Autoneg in SFI mode */ 3638 *ability = BSDK_PHY84728_PA_10000MB_FD | 3639 BSDK_PHY84728_PA_PAUSE; 3640 } 3641 } 3642 return SOC_E_NONE; 3643 } 3644 3645 3646 /* 3647 * Function: 3648 * bsdk_phy84728_remote_ability_advert_get 3649 * Purpose: 3650 * Get partners current advertisement for auto-negotiation. 3651 * Parameters: 3652 * phy_id - PHY Device Address 3653 * remote_ability - (OUT) Port ability mask indicating supported options/speeds. 3654 * For Speed & Duplex: 3655 * BSDK_PM_10MB_HD = 10Mb, Half Duplex 3656 * BSDK_PM_10MB_FD = 10Mb, Full Duplex 3657 * BSDK_PM_100MB_HD = 100Mb, Half Duplex 3658 * BSDK_PM_100MB_FD = 100Mb, Full Duplex 3659 * BSDK_PM_1000MB_HD = 1000Mb, Half Duplex 3660 * BSDK_PM_1000MB_FD = 1000Mb, Full Duplex 3661 * BSDK_PM_PAUSE_TX = TX Pause 3662 * BSDK_PM_PAUSE_RX = RX Pause 3663 * BSDK_PM_PAUSE_ASYMM = Asymmetric Pause 3664 * Returns: 3665 */ 3666 3667 int 3668 bsdk_phy84728_remote_ability_advert_get(phy_ctrl_t *pc, 3669 bsdk_phy84728_port_ability_t *remote_ability) 3670 { 3671 uint16 data = 0; 3672 bsdk_phy84728_intf_t line_mode; 3673 3674 if (remote_ability == NULL) { 3675 return SOC_E_PARAM; 3676 } 3677 3678 SOC_IF_ERROR_RETURN( 3679 bsdk_phy84728_line_intf_get(pc, 0, &line_mode)); 3680 3681 if (line_mode == BSDK_PHY84728_INTF_1000X) { 3682 SOC_IF_ERROR_RETURN( 3683 BSDK_RD_PHY84728_LN_DEV7_AN_ANPr(pc, &data)); 3684 3685 *remote_ability |= (data & BSDK_PHY84728_DEV7_1000X_ANA_C37_FD) ? 3686 BSDK_PHY84728_PA_1000MB_FD : 0; 3687 *remote_ability |= (data & BSDK_PHY84728_DEV7_1000X_ANA_C37_HD) ? 3688 BSDK_PHY84728_PA_1000MB_HD : 0; 3689 switch (data & (BSDK_PHY84728_DEV7_1000X_ANA_C37_PAUSE | 3690 BSDK_PHY84728_DEV7_1000X_ANA_C37_ASYM_PAUSE)) { 3691 case BSDK_PHY84728_DEV7_1000X_ANA_C37_PAUSE: 3692 *remote_ability |= BSDK_PHY84728_PA_PAUSE; 3693 break; 3694 case BSDK_PHY84728_DEV7_1000X_ANA_C37_ASYM_PAUSE: 3695 *remote_ability |= BSDK_PHY84728_PA_PAUSE_TX; 3696 break; 3697 case (BSDK_PHY84728_DEV7_1000X_ANA_C37_PAUSE | 3698 BSDK_PHY84728_DEV7_1000X_ANA_C37_ASYM_PAUSE): 3699 *remote_ability |= BSDK_PHY84728_PA_PAUSE_RX; 3700 break; 3701 } 3702 } else if (line_mode == BSDK_PHY84728_INTF_SGMII) { 3703 3704 3705 } else { 3706 if (!REVERSE_MODE(pc)) { 3707 /* No Autoneg in SFI mode */ 3708 return SOC_E_UNAVAIL; 3709 } 3710 } 3711 return SOC_E_NONE; 3712 } 3713 3714 3715 /* 3716 * Function: 3717 * bsdk_phy84728_ability_local_get 3718 * Purpose: 3719 * Get the PHY abilities 3720 * Parameters: 3721 * phy_id - PHY Device Address 3722 * mode - Mask indicating supported options/speeds. 3723 * For Speed & Duplex: 3724 * BSDK_PM_10MB_HD = 10Mb, Half Duplex 3725 * BSDK_PM_10MB_FD = 10Mb, Full Duplex 3726 * BSDK_PM_100MB_HD = 100Mb, Half Duplex 3727 * BSDK_PM_100MB_FD = 100Mb, Full Duplex 3728 * BSDK_PM_1000MB_HD = 1000Mb, Half Duplex 3729 * BSDK_PM_1000MB_FD = 1000Mb, Full Duplex 3730 * BSDK_PM_PAUSE_TX = TX Pause 3731 * BSDK_PM_PAUSE_RX = RX Pause 3732 * BSDK_PM_PAUSE_ASYMM = Asymmetric Pause 3733 * BSDK_PM_SGMII = SGMIII Supported 3734 * BSDK_PM_XSGMII = XSGMIII Supported 3735 * Returns: 3736 */ 3737 int 3738 bsdk_phy84728_ability_local_get(phy_ctrl_t *pc, 3739 bsdk_phy84728_port_ability_t *ability) 3740 { 3741 bsdk_phy84728_intf_t line_mode; 3742 3743 if (ability == NULL) { 3744 return SOC_E_PARAM; 3745 } 3746 3747 SOC_IF_ERROR_RETURN( 3748 bsdk_phy84728_line_intf_get(pc, 0, &line_mode)); 3749 3750 *ability = BSDK_PHY84728_PA_LB_PHY | BSDK_PHY84728_PA_PAUSE; 3751 *ability |= BSDK_PHY84728_PA_SGMII; 3752 3753 if (line_mode == BSDK_PHY84728_INTF_SGMII) { 3754 *ability |= BSDK_PHY84728_PA_AN; 3755 *ability |= BSDK_PHY84728_PA_SPEED_ALL; 3756 3757 } else { 3758 *ability |= BSDK_PHY84728_PA_XSGMII; 3759 *ability |= BSDK_PHY84728_PA_10000MB_FD; 3760 *ability |= BSDK_PHY84728_PA_1000MB_FD; 3761 } 3762 3763 return(SOC_E_NONE); 3764 } 3765 3766 STATIC int 3767 _bsdk_phy84728_system_sgmii_speed_set(phy_ctrl_t *pc, int dev_port, int speed) 3768 { 3769 uint16 mii_ctrl = 0; 3770 3771 if (speed == 0) { 3772 return SOC_E_NONE; 3773 } 3774 3775 { 3776 SOC_IF_ERROR_RETURN( 3777 BSDK_RD_PHY84728_SYS_DEV4_XGXS_MII_CTRLr(pc, &mii_ctrl)); 3778 3779 mii_ctrl &= ~(BSDK_PHY84728_AN_MII_CTRL_SS_MASK); 3780 switch(speed) { 3781 case 10: 3782 mii_ctrl |= BSDK_PHY84728_AN_MII_CTRL_SS_10; 3783 break; 3784 case 100: 3785 mii_ctrl |= BSDK_PHY84728_AN_MII_CTRL_SS_100; 3786 break; 3787 case 1000: 3788 mii_ctrl |= BSDK_PHY84728_AN_MII_CTRL_SS_1000; 3789 break; 3790 default: 3791 return SOC_E_CONFIG; 3792 } 3793 SOC_IF_ERROR_RETURN( 3794 BSDK_WR_PHY84728_SYS_DEV4_XGXS_MII_CTRLr(pc, mii_ctrl)); 3795 } 3796 return SOC_E_NONE; 3797 } 3798 3799 STATIC int 3800 _bsdk_phy84728_system_sgmii_duplex_set(phy_ctrl_t *pc, int dev_port, 3801 int duplex) 3802 { 3803 uint16 mii_ctrl; 3804 3805 { 3806 SOC_IF_ERROR_RETURN( 3807 BSDK_RD_PHY84728_SYS_DEV4_XGXS_MII_CTRLr(pc, &mii_ctrl)); 3808 3809 if ( duplex ) { 3810 mii_ctrl |= BSDK_PHY84728_AN_MII_CTRL_FD; 3811 } else { 3812 mii_ctrl &= ~BSDK_PHY84728_AN_MII_CTRL_FD; 3813 } 3814 SOC_IF_ERROR_RETURN( 3815 BSDK_WR_PHY84728_SYS_DEV4_XGXS_MII_CTRLr(pc, mii_ctrl)); 3816 } 3817 3818 return SOC_E_NONE; 3819 } 3820 3821 STATIC int 3822 _bsdk_phy84728_system_sgmii_sync(phy_ctrl_t *pc, int dev_port) 3823 { 3824 int speed; 3825 int duplex; 3826 3827 SOC_IF_ERROR_RETURN( 3828 phy_84728_speed_get(pc->unit, pc->port, &speed)); 3829 3830 SOC_IF_ERROR_RETURN( 3831 phy_84728_duplex_get(pc->unit, pc->port, &duplex)); 3832 3833 SOC_IF_ERROR_RETURN( 3834 BSDK_MOD_PHY84728_SYS_DEV4_XGXS_CTRLr(pc, 0x0000, BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ)); 3835 3836 SOC_IF_ERROR_RETURN( 3837 _bsdk_phy84728_system_sgmii_speed_set(pc, dev_port, speed)); 3838 3839 SOC_IF_ERROR_RETURN( 3840 _bsdk_phy84728_system_sgmii_duplex_set(pc, dev_port, duplex)); 3841 3842 SOC_IF_ERROR_RETURN( 3843 BSDK_MOD_PHY84728_SYS_DEV4_XGXS_CTRLr(pc, BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ, 3844 BSDK_PHY84728_AN_XGXS_CTRL_START_SEQ)); 3845 3846 return SOC_E_NONE; 3847 } 3848 3849 /* 3850 * Function: 3851 * bsdk_phy84728_mdio_firmware_download 3852 * Purpose: 3853 * Download new firmware via MDIO. 3854 * Parameters: 3855 * phy_id - PHY Device Address 3856 * new_fw - Pointer to new firmware 3857 * fw_length - Length of the firmware 3858 * Returns: 3859 */ 3860 int 3861 bsdk_phy84728_mdio_firmware_download(phy_ctrl_t *pc, 3862 uint8 *new_fw, uint32 fw_length) 3863 { 3864 3865 uint16 data16; 3866 int j; 3867 uint16 num_words; 3868 3869 /* 0xc848[15]=0, MDIO downloading to RAM, 0xc848[14]=1, serial boot */ 3870 /* 0xc848[13]=0, SPI-ROM downloading not done, 0xc848[2]=0, spi port enable */ 3871 SOC_IF_ERROR_RETURN( 3872 BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc848, 3873 (0 << 15)|(1 << 14), 3874 (1 << 15)|(1 << 14)|((1 << 13) | (1 << 2)))); 3875 3876 /* Reset, to download code from MDIO */ 3877 SOC_IF_ERROR_RETURN( 3878 BSDK_MOD_PHY84728_LN_DEV1_PMD_CTRLr(pc, 3879 BSDK_PHY84728_PMD_CTRL_RESET, BSDK_PHY84728_PMD_CTRL_RESET)); 3880 3881 sal_usleep(50000); 3882 3883 /* Write Starting Address, where the Code will reside in SRAM */ 3884 data16 = 0x8000; 3885 SOC_IF_ERROR_RETURN 3886 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, BSDK_PHY84728_PMAD_M8051_MSGIN_REG, data16)); 3887 3888 /* make sure address word is read by the micro */ 3889 sal_usleep(10); /* Wait for 10us */ 3890 3891 /* Write SPI SRAM Count Size */ 3892 data16 = (fw_length)/2; 3893 SOC_IF_ERROR_RETURN 3894 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, BSDK_PHY84728_PMAD_M8051_MSGIN_REG, data16)); 3895 3896 /* make sure read by the micro */ 3897 sal_usleep(10); /* Wait for 10us */ 3898 3899 /* Fill in the SRAM */ 3900 num_words = (fw_length - 1); 3901 for (j = 0; j < num_words; j+=2) { 3902 /* Make sure the word is read by the Micro */ 3903 sal_usleep(10); 3904 3905 data16 = (new_fw[j] << 8) | new_fw[j+1]; 3906 SOC_IF_ERROR_RETURN 3907 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, BSDK_PHY84728_PMAD_M8051_MSGIN_REG, 3908 data16)); 3909 } 3910 3911 /* make sure last code word is read by the micro */ 3912 sal_usleep(20); 3913 3914 /* Read Hand-Shake message (Done) from Micro */ 3915 SOC_IF_ERROR_RETURN 3916 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc,BSDK_PHY84728_PMAD_M8051_MSGOUT_REG, &data16)); 3917 3918 if (data16 != 0x4321 ) { 3919 /* Download done message */ 3920 LOG_CLI((BSL_META_U(pc->unit, 3921 "MDIO firmware download failed. Message: 0x%x\n"), data16)); 3922 } 3923 3924 /* Clear LASI status */ 3925 SOC_IF_ERROR_RETURN 3926 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0x9003, &data16)); 3927 3928 /* Wait for LASI to be asserted when M8051 writes checksum to MSG_OUTr */ 3929 sal_usleep(100); /* Wait for 100 usecs */ 3930 3931 SOC_IF_ERROR_RETURN 3932 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc,BSDK_PHY84728_PMAD_M8051_MSGOUT_REG, &data16)); 3933 3934 /* Need to check if checksum is correct */ 3935 SOC_IF_ERROR_RETURN 3936 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xCA1C, &data16)); 3937 3938 if (data16 != 0x600D) { 3939 /* Bad CHECKSUM */ 3940 LOG_CLI((BSL_META_U(pc->unit, 3941 "MDIO Firmware downlad failure:" 3942 "Incorrect Checksum %x\n"), data16)); 3943 return SOC_E_FAIL; 3944 } 3945 3946 /* read Rev-ID */ 3947 SOC_IF_ERROR_RETURN 3948 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xCA1A, &data16)); 3949 LOG_CLI((BSL_META_U(pc->unit, 3950 "MDIO Firmware download completed. Version : 0x%x\n"), data16)); 3951 3952 return SOC_E_NONE; 3953 } 3954 3955 /* 3956 * Function: 3957 * _phy_84728_phy_84728_write_message 3958 * 3959 * Purpose: 3960 * Write into Message In and Read from MSG Out register. 3961 * Input: 3962 * phy_id 3963 * wrdata 3964 * rddata 3965 */ 3966 3967 STATIC int 3968 _phy_84728_write_message(phy_ctrl_t *pc, uint16 wrdata, uint16 *rddata) 3969 { 3970 uint16 tmp_data = 0; 3971 int iter = 0; 3972 3973 SOC_IF_ERROR_RETURN 3974 (BSDK_RD_PHY84728_LN_DEV1_M8501_MSGOUTr(pc, &tmp_data)); 3975 SOC_IF_ERROR_RETURN 3976 (BSDK_WR_PHY84728_LN_DEV1_M8501_MSGINr(pc, wrdata)); 3977 3978 do { 3979 SOC_IF_ERROR_RETURN 3980 (BSDK_RD_PHY84728_LN_DEV1_LASI_STATr(pc, &tmp_data)); 3981 3982 if (tmp_data & 0x4) { 3983 break; 3984 } 3985 sal_usleep(BSDK_WR_TIMEOUT); 3986 iter++; 3987 } while (iter < BSDK_WR_ITERATIONS); 3988 3989 if (!(tmp_data & 0x4)) { 3990 LOG_CLI((BSL_META_U(pc->unit, 3991 "write message failed due to timeout\n"))); 3992 return SOC_E_FAIL; 3993 } 3994 3995 SOC_IF_ERROR_RETURN 3996 (BSDK_RD_PHY84728_LN_DEV1_M8501_MSGOUTr(pc, &tmp_data)); 3997 3998 *rddata = tmp_data; 3999 SOC_IF_ERROR_RETURN 4000 (BSDK_RD_PHY84728_LN_DEV1_RX_ALARMr(pc, &tmp_data)); 4001 4002 return SOC_E_NONE; 4003 } 4004 4005 4006 /* 4007 * Function: 4008 * _phy_84728_rom_wait 4009 * 4010 * Purpose: 4011 * Wait for data to be written to the SPI-ROM. 4012 * Input: 4013 * phy_id 4014 */ 4015 4016 STATIC int 4017 _phy_84728_rom_wait(phy_ctrl_t *pc) 4018 { 4019 uint16 rd_data = 0, wr_data; 4020 int count; 4021 int SPI_READY; 4022 int iter = 0; 4023 4024 do { 4025 count = 1; 4026 wr_data = ((BSDK_RD_CPU_CTRL_REGS * 0x0100) | count); 4027 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4028 wr_data = BSDK_SPI_CTRL_1_L; 4029 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4030 if (rd_data & 0x0100) { 4031 break; 4032 } 4033 sal_usleep(BSDK_WR_TIMEOUT); 4034 iter++; 4035 } while (iter < BSDK_WR_ITERATIONS); 4036 4037 if (!(rd_data & 0x0100)) { 4038 LOG_CLI((BSL_META_U(pc->unit, 4039 "_phy_84728_rom_wait: write timeout\n"))); 4040 return SOC_E_TIMEOUT; 4041 } 4042 4043 SPI_READY = 1; 4044 while (SPI_READY == 1) { 4045 /* Set-up SPI Controller To Receive SPI EEPROM Status. */ 4046 count = 1; 4047 wr_data = ((BSDK_WR_CPU_CTRL_REGS * 0x0100) | count); 4048 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4049 wr_data = BSDK_SPI_CTRL_2_H; 4050 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4051 wr_data = 0x0100; 4052 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4053 /* Fill-up SPI Transmit Fifo To check SPI Status. */ 4054 count = 2; 4055 wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count); 4056 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4057 /* Write Tx Fifo Register Address. */ 4058 wr_data = BSDK_SPI_TXFIFO; 4059 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4060 4061 /* Write SPI Tx Fifo Control Word-1. */ 4062 wr_data = ((1 * 0x0100) | BSDK_MSGTYPE_HRD); 4063 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4064 /* Write SPI Tx Fifo Control Word-2. */ 4065 wr_data = BSDK_RDSR_OPCODE; 4066 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4067 /* Write SPI Control Register Write Command. */ 4068 count = 2; 4069 wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count); 4070 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4071 /* Write SPI Control -1 Register Address. */ 4072 wr_data = BSDK_SPI_CTRL_1_L; 4073 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4074 /* Write SPI Control -1 Register Word-1. */ 4075 wr_data = 0x0101; 4076 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4077 /* Write SPI Control -1 Register Word-2. */ 4078 wr_data = 0x0100; 4079 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4080 /* Write SPI Control Register Write Command. */ 4081 count = 1; 4082 wr_data = ((BSDK_WR_CPU_CTRL_REGS * 0x0100) | count); 4083 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4084 /* Write SPI Control -1 Register Address. */ 4085 wr_data = BSDK_SPI_CTRL_1_H; 4086 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4087 /* Write SPI Control -1 Register Word-2. */ 4088 wr_data = 0x0103; 4089 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4090 /* Wait For 64 bytes To be written. */ 4091 rd_data = 0x0000; 4092 4093 do { 4094 count = 1; 4095 wr_data = ((BSDK_RD_CPU_CTRL_REGS * 0x0100) | count); 4096 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4097 wr_data = BSDK_SPI_CTRL_1_L; 4098 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4099 if (rd_data & 0x0100) { 4100 break; 4101 } 4102 sal_usleep(BSDK_WR_TIMEOUT); 4103 iter ++; 4104 } while (iter < BSDK_WR_ITERATIONS); 4105 4106 if (!(rd_data & 0x0100)) { 4107 LOG_CLI((BSL_META_U(pc->unit, 4108 "_phy_84728_rom_program:timeout 2\n"))); 4109 return SOC_E_TIMEOUT; 4110 } 4111 /* Write SPI Control Register Read Command. */ 4112 count = 1; 4113 wr_data = ((BSDK_RD_CPU_CTRL_REGS * 0x0100) | count); 4114 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4115 /* Write SPI Control -1 Register Address. */ 4116 wr_data = BSDK_SPI_RXFIFO; 4117 4118 SOC_IF_ERROR_RETURN 4119 (BSDK_WR_PHY84728_LN_DEV1_M8501_MSGINr(pc, wr_data)); 4120 SOC_IF_ERROR_RETURN 4121 (BSDK_RD_PHY84728_LN_DEV1_M8501_MSGOUTr(pc, &rd_data)); 4122 4123 /* Clear LASI Message Out Status. */ 4124 SOC_IF_ERROR_RETURN 4125 (BSDK_RD_PHY84728_LN_DEV1_LASI_STATr(pc, &wr_data)); 4126 4127 if ((rd_data & 0x1) == 0) { 4128 SPI_READY = 0; 4129 } 4130 } /* SPI_READY */ 4131 return SOC_E_NONE; 4132 } 4133 4134 4135 /* 4136 * Function: 4137 * _phy_84728_rom_write_enable_set 4138 * 4139 * Purpose: 4140 * Enable disable protection on SPI_EEPROM 4141 * 4142 * Input: 4143 * phy_id 4144 * Output: 4145 * SOC_E_xxx 4146 * 4147 * Notes: 4148 * 25AA256 256Kbit Serial EEPROM 4149 * STATUS Register 4150 * +------------------------------------------+ 4151 * | WPEN | x | x | x | BP1 | BP0 | WEL | WIP | 4152 * +------------------------------------------+ 4153 * BP1 BP0 : Protected Blocks 4154 * 0 0 : Protect None 4155 * 1 1 : Protect All 4156 * 4157 * WEL : Write Latch Enable 4158 * 0 : Do not allow writes 4159 * 1 : Allow writes 4160 */ 4161 STATIC int 4162 _phy_84728_rom_write_enable_set(phy_ctrl_t *pc, int enable) 4163 { 4164 uint16 rd_data, wr_data; 4165 uint8 wrsr_data; 4166 int count; 4167 4168 /* 4169 * Write SPI Control Register Write Command. 4170 */ 4171 count = 2; 4172 wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count); 4173 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4174 4175 /* 4176 * Write SPI Control -2 Register Address. 4177 */ 4178 wr_data = BSDK_SPI_CTRL_2_L; 4179 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4180 4181 /* 4182 * Write SPI Control -2 Register Word-1. 4183 */ 4184 wr_data = 0x8200; 4185 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4186 4187 /* 4188 * Write SPI Control -2 Register Word-2. 4189 */ 4190 wr_data = 0x0100; 4191 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4192 4193 /* 4194 * Fill-up SPI Transmit Fifo With SPI EEPROM Messages. 4195 * Write SPI Control Register Write Command. 4196 */ 4197 count = 4; 4198 wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count); 4199 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4200 4201 /* 4202 * Write Tx Fifo Register Address. 4203 */ 4204 wr_data = BSDK_SPI_TXFIFO; 4205 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4206 4207 /* 4208 * Write SPI Tx Fifo Control Word-1. 4209 */ 4210 wr_data = ((1 * 0x0100) | BSDK_MSGTYPE_HWR); 4211 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4212 4213 /* 4214 * Write SPI Tx Fifo Control Word-2. 4215 */ 4216 wr_data = ((BSDK_MSGTYPE_HWR * 0x0100) | BSDK_WREN_OPCODE); 4217 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4218 4219 /* 4220 * Write SPI Tx Fifo Control Word-3. 4221 */ 4222 wr_data = ((BSDK_WRSR_OPCODE * 0x100) | (0x2)); 4223 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4224 4225 /* 4226 * Write SPI Tx Fifo Control Word-4. 4227 */ 4228 wrsr_data = enable ? 0x2 : 0xc; 4229 wr_data = ((wrsr_data * 0x0100) | wrsr_data); 4230 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4231 4232 /* 4233 * Write SPI Control Register Write Command. 4234 */ 4235 count = 2; 4236 wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count); 4237 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4238 4239 /* 4240 * Write SPI Control -1 Register Address. 4241 */ 4242 wr_data = BSDK_SPI_CTRL_1_L; 4243 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4244 4245 /* 4246 * Write SPI Control -1 Register Word-1. 4247 */ 4248 wr_data = 0x0101; 4249 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4250 4251 /* 4252 * Write SPI Control -1 Register Word-2. 4253 */ 4254 wr_data = 0x0003; 4255 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4256 4257 /* 4258 * Wait For WRSR Command To be written. 4259 */ 4260 SOC_IF_ERROR_RETURN(_phy_84728_rom_wait(pc)); 4261 4262 return SOC_E_NONE; 4263 } 4264 4265 /* 4266 * Function: 4267 * bsdk_phy84728_spi_firmware_update 4268 * Purpose: 4269 * Update the firmware in SPI ROM 4270 * Parameters: 4271 * phy_id - PHY Device Address 4272 * new_fw - Pointer to new firmware 4273 * fw_length - Length of the firmware 4274 * Returns: 4275 */ 4276 int 4277 bsdk_phy84728_spi_firmware_update(phy_ctrl_t *pc, 4278 uint8 *array, uint32 datalen) 4279 { 4280 4281 uint16 data = 0; 4282 int j; 4283 uint16 rd_data, wr_data; 4284 uint8 spi_values[BSDK_WR_BLOCK_SIZE]; 4285 int count, i = 0; 4286 4287 4288 if (array == NULL) { 4289 return SOC_E_PARAM; 4290 } 4291 4292 /* Set Bit 2 and Bit 0 in SPI Control */ 4293 SOC_IF_ERROR_RETURN( 4294 BSDK_MOD_PHY84728_LN_DEV1_SPI_CTRL_STATr(pc, 0x80FD, 0xffff)); 4295 4296 /* ser_boot pin high */ 4297 SOC_IF_ERROR_RETURN( 4298 BSDK_MOD_PHY84728_LN_DEV1_MISC_CNTL2r(pc, 0x1, 0x1)); 4299 4300 /* Read LASI Status */ 4301 SOC_IF_ERROR_RETURN( 4302 BSDK_RD_PHY84728_LN_DEV1_RX_ALARM_STATr(pc, &data)); 4303 SOC_IF_ERROR_RETURN( 4304 BSDK_RD_PHY84728_LN_DEV1_TX_ALARM_STATr(pc, &data)); 4305 SOC_IF_ERROR_RETURN( 4306 BSDK_RD_PHY84728_LN_DEV1_LASI_STATr(pc, &data)); 4307 4308 /* Enable LASI for Message Out */ 4309 SOC_IF_ERROR_RETURN( 4310 BSDK_MOD_PHY84728_LN_DEV1_RX_ALARM_CNTLr(pc, 0x4, 0x4)); 4311 4312 /* Enable RX Alarm in LASI */ 4313 SOC_IF_ERROR_RETURN( 4314 BSDK_MOD_PHY84728_LN_DEV1_LASI_CNTLr(pc, 0x4, 0x4)); 4315 4316 /* Read any residual Message out register */ 4317 SOC_IF_ERROR_RETURN( 4318 BSDK_RD_PHY84728_LN_DEV1_M8501_MSGOUTr(pc, &data)); 4319 4320 /* Clear LASI Message OUT status */ 4321 SOC_IF_ERROR_RETURN( 4322 BSDK_RD_PHY84728_LN_DEV1_RX_ALARM_STATr(pc, &data)); 4323 4324 /* Set SPI-ROM write enable */ 4325 SOC_IF_ERROR_RETURN( 4326 _phy_84728_rom_write_enable_set(pc, 1)); 4327 4328 4329 for (j = 0; j < datalen; j +=BSDK_WR_BLOCK_SIZE) { 4330 /* Setup SPI Controller */ 4331 count = 2; 4332 wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count); 4333 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4334 4335 /* Write SPI Control -2 Register Address.*/ 4336 wr_data = BSDK_SPI_CTRL_2_L; 4337 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4338 4339 /* Write SPI Control -2 Register Word-1. */ 4340 wr_data = 0x8200; 4341 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4342 4343 /* Write SPI Control -2 Register Word-2. */ 4344 wr_data = 0x0100; 4345 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4346 4347 /* Fill-up SPI Transmit Fifo. 4348 * Write SPI Control Register Write Command. 4349 */ 4350 count = 4 + (BSDK_WR_BLOCK_SIZE / 2); 4351 wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count); 4352 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4353 4354 /* Write Tx Fifo Register Address. */ 4355 wr_data = BSDK_SPI_TXFIFO; 4356 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4357 4358 /* Write SPI Tx Fifo Control Word-1. */ 4359 wr_data = ((1 * 0x0100) | BSDK_MSGTYPE_HWR); 4360 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4361 4362 /* Write SPI Tx Fifo Control Word-2. */ 4363 wr_data = ((BSDK_MSGTYPE_HWR * 0x0100) | BSDK_WREN_OPCODE); 4364 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4365 4366 /* Write SPI Tx Fifo Control Word-3. */ 4367 wr_data = ((BSDK_WR_OPCODE * 0x0100) | (0x3 + BSDK_WR_BLOCK_SIZE)); 4368 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4369 4370 /* Write SPI Tx Fifo Control Word-4. */ 4371 wr_data = (((j & 0x00FF) * 0x0100) | ((j & 0xFF00) / 0x0100)); 4372 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4373 4374 if (datalen < (j + BSDK_WR_BLOCK_SIZE)) { /* last block */ 4375 sal_memset(spi_values,0,BSDK_WR_BLOCK_SIZE); 4376 sal_memcpy(spi_values,&array[j],datalen - j); 4377 4378 for (i = 0; i < BSDK_WR_BLOCK_SIZE; i += 2) { 4379 /* Write SPI Tx Fifo Data Word-4. */ 4380 wr_data = ((spi_values[i+1] * 0x0100) | spi_values[i]); 4381 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4382 } 4383 } else { 4384 for (i = 0; i < BSDK_WR_BLOCK_SIZE; i += 2) { 4385 /* Write SPI Tx Fifo Data Word-4. */ 4386 wr_data = ((array[j+i+1] * 0x0100) | array[j+i]); 4387 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4388 } 4389 } 4390 4391 /* 4392 * Set-up SPI Controller To Transmit. 4393 * Write SPI Control Register Write Command. 4394 */ 4395 count = 2; 4396 wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count); 4397 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4398 4399 wr_data = BSDK_SPI_CTRL_1_L; 4400 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4401 4402 /* Write SPI Control -1 Register Word-1. */ 4403 wr_data = 0x0501; 4404 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4405 4406 /* Write SPI Control -1 Register Word-2. */ 4407 wr_data = 0x0003; 4408 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4409 4410 /* Wait For 64 bytes To be written. */ 4411 SOC_IF_ERROR_RETURN(_phy_84728_rom_wait(pc)); 4412 } 4413 4414 /* Clear SPI-ROM write enable */ 4415 SOC_IF_ERROR_RETURN( 4416 _phy_84728_rom_write_enable_set(pc, 0)); 4417 4418 /* Disable SPI EEPROM. */ 4419 count = 2; 4420 wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count); 4421 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4422 4423 /* Write SPI Control -2 Register Address. */ 4424 wr_data = BSDK_SPI_CTRL_2_L; 4425 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4426 4427 /* Write SPI Control -2 Register Word-1. */ 4428 wr_data = 0x8200; 4429 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4430 4431 /* Write SPI Control -2 Register Word-2. */ 4432 wr_data = 0x0100; 4433 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4434 4435 4436 /* Fill-up SPI Transmit Fifo With SPI EEPROM Messages. */ 4437 count = 2; 4438 wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count); 4439 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4440 4441 /* Write Tx Fifo Register Address. */ 4442 wr_data = BSDK_SPI_TXFIFO; 4443 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4444 4445 /* Write SPI Tx Fifo Control Word-1. */ 4446 wr_data = ((0x1*0x0100) | BSDK_MSGTYPE_HWR); 4447 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4448 4449 /* Write SPI Tx Fifo Control Word-2. */ 4450 wr_data = BSDK_WRDI_OPCODE; 4451 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4452 4453 /* Write SPI Control Register Write Command. */ 4454 count = 2; 4455 wr_data = ((BSDK_WR_CPU_CTRL_FIFO * 0x0100) | count); 4456 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4457 4458 /* Write SPI Control -1 Register Address. */ 4459 wr_data = BSDK_SPI_CTRL_1_L; 4460 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4461 4462 /* Write SPI Control -1 Register Word-1. */ 4463 wr_data = 0x0101; 4464 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4465 4466 /* Write SPI Control -1 Register Word-2. */ 4467 wr_data = 0x0003; 4468 SOC_IF_ERROR_RETURN(_phy_84728_write_message(pc, wr_data, &rd_data)); 4469 4470 /* ser_boot pin LOW */ 4471 SOC_IF_ERROR_RETURN( 4472 BSDK_MOD_PHY84728_LN_DEV1_MISC_CNTL2r(pc, 0x0, 0x1)); 4473 4474 /* Disable Bit 2 and Bit 0 in SPI Control */ 4475 SOC_IF_ERROR_RETURN( 4476 BSDK_MOD_PHY84728_LN_DEV1_SPI_CTRL_STATr(pc, 0xc0F9, 0xffff)); 4477 4478 return SOC_E_NONE; 4479 } 4480 4481 STATIC int 4482 _phy_84728_bsc_rw(phy_ctrl_t *pc, int dev_addr, int opr, 4483 int addr, int count, void *data_array,uint32 ram_start) 4484 { 4485 int rv = SOC_E_NONE; 4486 int iter = 0; 4487 uint16 data16; 4488 int i; 4489 int access_type; 4490 int data_type; 4491 4492 if (!data_array) { 4493 return SOC_E_PARAM; 4494 } 4495 4496 if (count > BSDK_PHY84728_BSC_XFER_MAX) { 4497 return SOC_E_PARAM; 4498 } 4499 4500 data_type = BSDK_PHY84728_I2C_DATA_TYPE(opr); 4501 access_type = BSDK_PHY84728_I2C_ACCESS_TYPE(opr); 4502 4503 if (access_type == BSDK_PHY84728_I2CDEV_WRITE) { 4504 for (i = 0; i < count; i++) { 4505 if (data_type == BSDK_PHY84728_I2C_8BIT) { 4506 SOC_IF_ERROR_RETURN 4507 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, ram_start + i, 4508 ((uint8 *)data_array)[i])); 4509 } else { /* 16 bit */ 4510 SOC_IF_ERROR_RETURN 4511 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, ram_start + i, 4512 ((uint16 *)data_array)[i])); 4513 } 4514 } 4515 } 4516 4517 data16 = ram_start; 4518 SOC_IF_ERROR_RETURN 4519 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0x8004, data16)); 4520 SOC_IF_ERROR_RETURN 4521 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0x8003, addr)); 4522 SOC_IF_ERROR_RETURN 4523 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0x8002, count)); 4524 4525 data16 = 1; 4526 data16 |= (dev_addr<<9); 4527 if (access_type == BSDK_PHY84728_I2CDEV_WRITE) { 4528 data16 |= BSDK_PHY84728_WR_FREQ_400KHZ; 4529 } 4530 4531 SOC_IF_ERROR_RETURN 4532 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0x8005,data16)); 4533 4534 if (access_type == BSDK_PHY84728_I2CDEV_WRITE) { 4535 data16 = 0x8000 | BSDK_PHY84728_BSC_WRITE_OP; 4536 } else { 4537 data16 = 0x8000 | BSDK_PHY84728_BSC_READ_OP; 4538 } 4539 4540 if (data_type == BSDK_PHY84728_I2C_16BIT) { 4541 data16 |= (1 << 12); 4542 } 4543 4544 /* for single port mode, there should be only one I2C interface active 4545 * from lane0. The 0x800x register block is bcst type registers. If writing 4546 * to 0x8000 directly, it will enable all four I2C masters. Use indirect access 4547 * to enable only the lane 0. 4548 */ 4549 4550 SOC_IF_ERROR_RETURN 4551 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0x8000, data16)); 4552 4553 while (iter < 100000) { 4554 rv = BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0x8000, &data16); 4555 if (((data16 & BSDK_PHY84728_2W_STAT) == BSDK_PHY84728_2W_STAT_COMPLETE)) { 4556 break; 4557 } 4558 iter++; 4559 } 4560 4561 /* need some delays */ 4562 sal_usleep(10000); 4563 4564 LOG_CLI((BSL_META_U(pc->unit, 4565 "BSC command status %d\n"),(data16 & BSDK_PHY84728_2W_STAT))); 4566 4567 if (access_type == BSDK_PHY84728_I2CDEV_WRITE) { 4568 return SOC_E_NONE; 4569 } 4570 4571 if ((data16 & BSDK_PHY84728_2W_STAT) == BSDK_PHY84728_2W_STAT_COMPLETE) { 4572 for (i = 0; i < count; i++) { 4573 SOC_IF_ERROR_RETURN 4574 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, (ram_start+i), &data16)); 4575 if (data_type == BSDK_PHY84728_I2C_16BIT) { 4576 ((uint16 *)data_array)[i] = data16; 4577 LOG_CLI((BSL_META_U(pc->unit, 4578 "%04x "), data16)); 4579 } else { 4580 ((uint8 *)data_array)[i] = (uint8)data16; 4581 LOG_CLI((BSL_META_U(pc->unit, 4582 "%02x "), data16)); 4583 } 4584 } 4585 } 4586 return rv; 4587 } 4588 4589 /* 4590 * Read a slave device such as NVRAM/EEPROM connected to the 84728's I2C 4591 * interface. This function will be mainly used for diagnostic or workaround 4592 * purpose. 4593 * Note: 4594 * The size of read_array buffer must be greater than or equal to the 4595 * parameter nbytes. 4596 * usage example: 4597 * Retrieve the first 100 byte data of the non-volatile storage device with 4598 * I2C bus device address 0x50(default SPF eeprom I2C address) on unit 0, 4599 * port 2. 4600 * uint8 data8[100]; 4601 * phy_84728_i2cdev_read(0,2,0x50,0,100,data8); 4602 */ 4603 int 4604 bsdk_phy_84728_i2cdev_read(phy_ctrl_t *pc, 4605 int dev_addr, /* 7 bit I2C bus device address */ 4606 int offset, /* starting data address to read */ 4607 int nbytes, /* number of bytes to read */ 4608 uint8 *read_array) /* buffer to hold retrieved data */ 4609 { 4610 return _phy_84728_bsc_rw(pc, dev_addr,BSDK_PHY84728_I2CDEV_READ, 4611 offset, nbytes, (void *)read_array,BSDK_PHY84728_READ_START_ADDR); 4612 4613 } 4614 4615 /* 4616 * Write to a slave device such as NVRAM/EEPROM connected to the 84728's I2C 4617 * interface. This function will be mainly used for diagnostic or workaround 4618 * purpose. 4619 * Note: 4620 * The size of write_array buffer should be equal to the parameter nbytes. 4621 * The EEPROM may limit the maximun write size to 16 bytes 4622 * usage example: 4623 * Write to first 100 byte space of the non-volatile storage device with 4624 * I2C bus device address 0x50(default SPF eeprom I2C address) on unit 0, 4625 * port 2, with written data specified in array data8. 4626 * uint8 data8[100]; 4627 * *** initialize the data8 array with written data *** 4628 * 4629 * phy_84728_i2cdev_write(0,2,0x50,0,100,data8); 4630 */ 4631 4632 int 4633 bsdk_phy_84728_i2cdev_write(phy_ctrl_t *pc, 4634 int dev_addr, /* I2C bus device address */ 4635 int offset, /* starting data address to write to */ 4636 int nbytes, /* number of bytes to write */ 4637 uint8 *write_array) /* buffer to hold written data */ 4638 { 4639 int j; 4640 int rv = SOC_E_NONE; 4641 4642 for (j = 0; j < (nbytes/BSDK_PHY84728_BSC_WR_MAX); j++) { 4643 rv = _phy_84728_bsc_rw(pc, dev_addr,BSDK_PHY84728_I2CDEV_WRITE, 4644 offset + j * BSDK_PHY84728_BSC_WR_MAX, BSDK_PHY84728_BSC_WR_MAX, 4645 (void *)(write_array + j * BSDK_PHY84728_BSC_WR_MAX), 4646 BSDK_PHY84728_WRITE_START_ADDR); 4647 if (rv != SOC_E_NONE) { 4648 return rv; 4649 } 4650 sal_usleep(20000); 4651 } 4652 if (nbytes%BSDK_PHY84728_BSC_WR_MAX) { 4653 rv = _phy_84728_bsc_rw(pc, dev_addr,BSDK_PHY84728_I2CDEV_WRITE, 4654 offset + j * BSDK_PHY84728_BSC_WR_MAX, nbytes%BSDK_PHY84728_BSC_WR_MAX, 4655 (void *)(write_array + j * BSDK_PHY84728_BSC_WR_MAX), 4656 BSDK_PHY84728_WRITE_START_ADDR); 4657 } 4658 return rv; 4659 } 4660 4661 void _phy_84728_encode_egress_message_mode(soc_port_phy_timesync_event_message_egress_mode_t mode, 4662 int offset, uint16 *value) 4663 { 4664 4665 switch (mode) { 4666 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE: 4667 *value |= (0x0 << offset); 4668 break; 4669 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD: 4670 *value |= (0x1 << offset); 4671 break; 4672 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN: 4673 *value |= (0x2 << offset); 4674 break; 4675 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP: 4676 *value |= (0x3 << offset); 4677 break; 4678 } 4679 4680 } 4681 4682 void _phy_84728_encode_ingress_message_mode(soc_port_phy_timesync_event_message_ingress_mode_t mode, 4683 int offset, uint16 *value) 4684 { 4685 4686 switch (mode) { 4687 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE: 4688 *value |= (0x0 << offset); 4689 break; 4690 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD: 4691 *value |= (0x1 << offset); 4692 break; 4693 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP: 4694 *value |= (0x2 << offset); 4695 break; 4696 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME: 4697 *value |= (0x3 << offset); 4698 break; 4699 } 4700 4701 } 4702 4703 void _phy_84728_decode_egress_message_mode(uint16 value, int offset, 4704 soc_port_phy_timesync_event_message_egress_mode_t *mode) 4705 { 4706 4707 switch ((value >> offset) & 0x3) { 4708 case 0x0: 4709 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE; 4710 break; 4711 case 0x1: 4712 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD; 4713 break; 4714 case 0x2: 4715 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN; 4716 break; 4717 case 0x3: 4718 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP; 4719 break; 4720 } 4721 4722 } 4723 4724 void _phy_84728_decode_ingress_message_mode(uint16 value, int offset, 4725 soc_port_phy_timesync_event_message_ingress_mode_t *mode) 4726 { 4727 4728 switch ((value >> offset) & 0x3) { 4729 case 0x0: 4730 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE; 4731 break; 4732 case 0x1: 4733 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD; 4734 break; 4735 case 0x2: 4736 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP; 4737 break; 4738 case 0x3: 4739 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME; 4740 break; 4741 } 4742 4743 } 4744 4745 void _phy_84728_encode_gmode(soc_port_phy_timesync_global_mode_t mode, 4746 uint16 *value) 4747 { 4748 4749 switch (mode) { 4750 case SOC_PORT_PHY_TIMESYNC_MODE_FREE: 4751 *value = 0x1; 4752 break; 4753 case SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN: 4754 *value = 0x2; 4755 break; 4756 case SOC_PORT_PHY_TIMESYNC_MODE_CPU: 4757 *value = 0x3; 4758 break; 4759 default: 4760 break; 4761 } 4762 4763 } 4764 4765 void _phy_84728_decode_gmode(uint16 value, 4766 soc_port_phy_timesync_global_mode_t *mode) 4767 { 4768 4769 switch (value & 0x3) { 4770 case 0x1: 4771 *mode = SOC_PORT_PHY_TIMESYNC_MODE_FREE; 4772 break; 4773 case 0x2: 4774 *mode = SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN; 4775 break; 4776 case 0x3: 4777 *mode = SOC_PORT_PHY_TIMESYNC_MODE_CPU; 4778 break; 4779 default: 4780 break; 4781 } 4782 4783 } 4784 4785 4786 void _phy_84728_encode_framesync_mode(soc_port_phy_timesync_framesync_mode_t mode, 4787 uint16 *value) 4788 { 4789 4790 switch (mode) { 4791 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0: 4792 *value = 1U << 0; 4793 break; 4794 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1: 4795 *value = 1U << 1; 4796 break; 4797 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT: 4798 *value = 1U << 2; 4799 break; 4800 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU: 4801 *value = 1U << 3; 4802 break; 4803 default: 4804 break; 4805 } 4806 4807 } 4808 4809 void _phy_84728_decode_framesync_mode(uint16 value, 4810 soc_port_phy_timesync_framesync_mode_t *mode) 4811 { 4812 4813 switch (value & 0xf) { 4814 case 1U << 0: 4815 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0; 4816 break; 4817 case 1U << 1: 4818 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1; 4819 break; 4820 case 1U << 2: 4821 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT; 4822 break; 4823 case 1U << 3: 4824 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU; 4825 break; 4826 default: 4827 break; 4828 } 4829 4830 } 4831 4832 void _phy_84728_encode_syncout_mode(soc_port_phy_timesync_syncout_mode_t mode, 4833 uint16 *value) 4834 { 4835 4836 switch (mode) { 4837 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE: 4838 *value = 0x0; 4839 break; 4840 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME: 4841 *value = 0x1; 4842 break; 4843 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN: 4844 *value = 0x2; 4845 break; 4846 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC: 4847 *value = 0x3; 4848 break; 4849 } 4850 4851 } 4852 4853 void _phy_84728_decode_syncout_mode(uint16 value, 4854 soc_port_phy_timesync_syncout_mode_t *mode) 4855 { 4856 4857 switch (value & 0x3) { 4858 case 0x0: 4859 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE; 4860 break; 4861 case 0x1: 4862 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME; 4863 break; 4864 case 0x2: 4865 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN; 4866 break; 4867 case 0x3: 4868 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC; 4869 break; 4870 } 4871 4872 } 4873 4874 4875 int 4876 phy_84728_timesync_config_set(int unit, soc_port_t port, soc_port_phy_timesync_config_t *conf) 4877 { 4878 uint16 rx_control_reg = 0, tx_control_reg = 0, rx_tx_control_reg = 0, 4879 en_control_reg = 0, capture_en_reg = 0, 4880 nse_sc_8 = 0, nse_nco_3 = 0, value, mpls_control_reg = 0, temp = 0, 4881 gmode = 0, framesync_mode = 0, syncout_mode = 0, mask = 0, 4882 pulse_1_length, pulse_2_length, length_threshold, event_offset; 4883 uint32 interval; 4884 int i; 4885 phy_ctrl_t *pc; 4886 4887 pc = EXT_PHY_SW_STATE(unit, port); 4888 4889 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) { 4890 4891 if (conf->flags & SOC_PORT_PHY_TIMESYNC_ENABLE) { 4892 SOC_IF_ERROR_RETURN 4893 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc600, 0x0003)); 4894 #if 0 4895 SOC_IF_ERROR_RETURN 4896 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc8f0, 0x0000)); 4897 #endif 4898 en_control_reg |= 3U; 4899 nse_sc_8 |= (1U << 12); 4900 } 4901 4902 /* slice enable control reg */ 4903 SOC_IF_ERROR_RETURN 4904 (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc600, en_control_reg, 4905 3U)); 4906 4907 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE) { 4908 capture_en_reg |= 3U; 4909 } 4910 4911 /* TXRX SOP TS CAPTURE ENABLE reg */ 4912 SOC_IF_ERROR_RETURN 4913 (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc607, capture_en_reg, 3U)); 4914 4915 if (conf->flags & SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE) { 4916 nse_sc_8 |= (1U << 13); 4917 } 4918 4919 /* NSE SC 8 register */ 4920 SOC_IF_ERROR_RETURN 4921 (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc63a, nse_sc_8, 4922 (1U << 12)| (1U << 13))); 4923 4924 if (conf->flags & SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE) { 4925 rx_tx_control_reg |= (1U << 3); 4926 } 4927 4928 /* RX TX CONTROL register */ 4929 SOC_IF_ERROR_RETURN 4930 (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc61c, rx_tx_control_reg, (1U << 3))); 4931 4932 if (conf->flags & SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE) { 4933 rx_control_reg |= (1U << 3); 4934 tx_control_reg |= (1U << 3); 4935 } 4936 4937 if (conf->flags & SOC_PORT_PHY_TIMESYNC_L2_ENABLE) { 4938 rx_control_reg |= (1U << 2); 4939 tx_control_reg |= (1U << 2); 4940 } 4941 4942 if (conf->flags & SOC_PORT_PHY_TIMESYNC_IP4_ENABLE) { 4943 rx_control_reg |= (1U << 1); 4944 tx_control_reg |= (1U << 1); 4945 } 4946 4947 if (conf->flags & SOC_PORT_PHY_TIMESYNC_IP6_ENABLE) { 4948 rx_control_reg |= (1U << 0); 4949 tx_control_reg |= (1U << 0); 4950 } 4951 4952 /* TX CONTROL register */ 4953 SOC_IF_ERROR_RETURN 4954 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc618, tx_control_reg)); 4955 4956 /* RX CONTROL register */ 4957 SOC_IF_ERROR_RETURN 4958 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc61a, rx_control_reg)); 4959 4960 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT) { 4961 nse_nco_3 &= (uint16) ~(1U << 14); 4962 } else { 4963 nse_nco_3 |= (1U << 14); 4964 } 4965 4966 /* NSE NCO 3 register */ 4967 SOC_IF_ERROR_RETURN 4968 (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc630, nse_nco_3, 4969 (1U << 14))); 4970 } 4971 4972 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) { 4973 /* VLAN TAG register */ 4974 SOC_IF_ERROR_RETURN 4975 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc61d, conf->itpid)); 4976 } 4977 4978 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) { 4979 /* OUTER VLAN TAG register */ 4980 SOC_IF_ERROR_RETURN 4981 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc61e, conf->otpid)); 4982 } 4983 4984 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) { 4985 /* INNER VLAN TAG register */ 4986 SOC_IF_ERROR_RETURN 4987 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc61f, conf->otpid2)); 4988 } 4989 4990 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) { 4991 SOC_IF_ERROR_RETURN 4992 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc636, conf->ts_divider & 0xfff)); 4993 } 4994 4995 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) { 4996 SOC_IF_ERROR_RETURN 4997 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc605, conf->rx_link_delay & 0xffff)); 4998 SOC_IF_ERROR_RETURN 4999 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc606, (conf->rx_link_delay >> 16) & 0xffff)); 5000 } 5001 5002 5003 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) { 5004 5005 /* TIME CODE 5 register */ 5006 SOC_IF_ERROR_RETURN 5007 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc610, (uint16)(conf->original_timecode.nanoseconds & 0xffff))); 5008 5009 /* TIME CODE 4 register */ 5010 SOC_IF_ERROR_RETURN 5011 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc60f, (uint16)((conf->original_timecode.nanoseconds >> 16) & 0xffff))); 5012 5013 /* TIME CODE 3 register */ 5014 SOC_IF_ERROR_RETURN 5015 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc60e, (uint16)(COMPILER_64_LO(conf->original_timecode.seconds) & 0xffff))); 5016 5017 /* TIME CODE 2 register */ 5018 SOC_IF_ERROR_RETURN 5019 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc60d, (uint16)((COMPILER_64_LO(conf->original_timecode.seconds) >> 16) & 0xffff))); 5020 5021 /* TIME CODE 1 register */ 5022 SOC_IF_ERROR_RETURN 5023 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc60c, (uint16)(COMPILER_64_HI(conf->original_timecode.seconds) & 0xffff))); 5024 } 5025 5026 mask = 0; 5027 5028 /* NSE SC 8 register */ 5029 5030 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) { 5031 _phy_84728_encode_gmode(conf->gmode,&gmode); 5032 mask |= (0x3 << 14); 5033 } 5034 5035 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) { 5036 _phy_84728_encode_framesync_mode(conf->framesync.mode, &framesync_mode); 5037 mask |= (0xf << 2) | (0x1 << 11); 5038 5039 /* Divide by 6.4 without floating point */ 5040 length_threshold = (conf->framesync.length_threshold * 10) / 64; 5041 event_offset = (conf->framesync.event_offset * 10) / 64; 5042 5043 SOC_IF_ERROR_RETURN 5044 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63c, length_threshold)); 5045 SOC_IF_ERROR_RETURN 5046 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63b, event_offset)); 5047 } 5048 5049 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) { 5050 _phy_84728_encode_syncout_mode(conf->syncout.mode, &syncout_mode); 5051 mask |= (0x3 << 0); 5052 5053 /* Divide by 6.4 without floating point */ 5054 interval = (conf->syncout.interval * 10) / 64; 5055 pulse_1_length = (conf->syncout.pulse_1_length * 10) / 64; 5056 pulse_2_length = (conf->syncout.pulse_2_length * 10) / 64; 5057 5058 SOC_IF_ERROR_RETURN 5059 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc635, interval & 0xffff)); 5060 SOC_IF_ERROR_RETURN 5061 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc634, 5062 ((pulse_2_length & 0x3) << 14) | ((interval >> 16) & 0x3fff))); 5063 SOC_IF_ERROR_RETURN 5064 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc633, 5065 ((pulse_1_length & 0x1ff) << 7) | ((pulse_2_length >> 2) & 0x7f))); 5066 5067 SOC_IF_ERROR_RETURN 5068 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc639, 5069 (uint16)(COMPILER_64_LO(conf->syncout.syncout_ts) & 0xfff0))); 5070 SOC_IF_ERROR_RETURN 5071 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc638, 5072 (uint16)((COMPILER_64_LO(conf->syncout.syncout_ts) >> 16) & 0xffff))); 5073 SOC_IF_ERROR_RETURN 5074 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc637, 5075 (uint16)(COMPILER_64_HI(conf->syncout.syncout_ts) & 0xffff))); 5076 } 5077 5078 SOC_IF_ERROR_RETURN 5079 (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc63a, (gmode << 14) | 5080 ((framesync_mode & 0x2) ? (1U << 11) : (1U << 6)) | /* if bits 1 or 2 are set, turn off syncout */ 5081 (framesync_mode << 2) | (syncout_mode << 0), mask)); 5082 5083 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) { 5084 /* RX_TS_Offset[19:0] = (1.0xC67B[7:4]) | (1.0xC60B[15:0]) */ 5085 SOC_IF_ERROR_RETURN 5086 (BSDK_WR_PHY84728_LN_DEV1_PMDr( pc, 0xc60b, 5087 (uint16) ( conf->rx_timestamp_offset & 0x0ffff)) ); 5088 SOC_IF_ERROR_RETURN 5089 (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc67b, 5090 (uint16) (((conf->rx_timestamp_offset & 0xf0000)) >> 12), 5091 (0xf << 4)) ); 5092 } 5093 5094 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) { 5095 /* TX_TS_Offset[19:0] = (1.0xC67B[3:0]) | (1.0xC60A[15:0]) */ 5096 SOC_IF_ERROR_RETURN 5097 (BSDK_WR_PHY84728_LN_DEV1_PMDr( pc, 0xc60a, 5098 (uint16) ( conf->tx_timestamp_offset & 0x0ffff)) ); 5099 SOC_IF_ERROR_RETURN 5100 (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc67b, 5101 (uint16) (((conf->tx_timestamp_offset & 0xf0000)) >> 16), 5102 (0xf << 0)) ); 5103 } 5104 5105 value = mask = 0; 5106 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) { 5107 _phy_84728_encode_egress_message_mode(conf->tx_sync_mode, 0, &value); 5108 mask |= 0x3 << 0; 5109 } 5110 5111 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) { 5112 _phy_84728_encode_egress_message_mode(conf->tx_delay_request_mode, 2, &value); 5113 mask |= 0x3 << 2; 5114 } 5115 5116 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) { 5117 _phy_84728_encode_egress_message_mode(conf->tx_pdelay_request_mode, 4, &value); 5118 mask |= 0x3 << 4; 5119 } 5120 5121 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) { 5122 _phy_84728_encode_egress_message_mode(conf->tx_pdelay_response_mode, 6, &value); 5123 mask |= 0x3 << 6; 5124 } 5125 5126 /* TX EVENT MESSAGE MODE SEL register */ 5127 SOC_IF_ERROR_RETURN 5128 (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc601, value, mask)); 5129 5130 value = mask = 0; 5131 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) { 5132 _phy_84728_encode_ingress_message_mode(conf->rx_sync_mode, 0, &value); 5133 mask |= 0x3 << 0; 5134 } 5135 5136 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) { 5137 _phy_84728_encode_ingress_message_mode(conf->rx_delay_request_mode, 2, &value); 5138 mask |= 0x3 << 2; 5139 } 5140 5141 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) { 5142 _phy_84728_encode_ingress_message_mode(conf->rx_pdelay_request_mode, 4, &value); 5143 mask |= 0x3 << 4; 5144 } 5145 5146 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) { 5147 _phy_84728_encode_ingress_message_mode(conf->rx_pdelay_response_mode, 6, &value); 5148 mask |= 0x3 << 6; 5149 } 5150 5151 /* RX EVENT MESSAGE MODE SEL register */ 5152 SOC_IF_ERROR_RETURN 5153 (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc603, value, mask)); 5154 5155 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) { 5156 5157 /* Initial ref phase [15:0] */ 5158 SOC_IF_ERROR_RETURN 5159 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc623, (uint16)(COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) & 0xffff))); 5160 5161 /* Initial ref phase [31:16] */ 5162 SOC_IF_ERROR_RETURN 5163 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc622, (uint16)((COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) >> 16) & 0xffff))); 5164 5165 /* Initial ref phase [47:32] */ 5166 SOC_IF_ERROR_RETURN 5167 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc621, (uint16)(COMPILER_64_HI(conf->phy_1588_dpll_ref_phase) & 0xffff))); 5168 } 5169 5170 5171 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) { 5172 SOC_IF_ERROR_RETURN 5173 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc625, conf->phy_1588_dpll_ref_phase_delta & 0xffff)); 5174 SOC_IF_ERROR_RETURN 5175 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc624, (conf->phy_1588_dpll_ref_phase_delta >> 16) & 0xffff)); 5176 } 5177 5178 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) { 5179 /* DPLL K1 */ 5180 SOC_IF_ERROR_RETURN 5181 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc626, conf->phy_1588_dpll_k1 & 0xff)); 5182 } 5183 5184 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) { 5185 /* DPLL K2 */ 5186 SOC_IF_ERROR_RETURN 5187 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc627, conf->phy_1588_dpll_k2 & 0xff)); 5188 } 5189 5190 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) { 5191 /* DPLL K3 */ 5192 SOC_IF_ERROR_RETURN 5193 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc628, conf->phy_1588_dpll_k3 & 0xff)); 5194 } 5195 5196 5197 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL) { 5198 5199 /* MPLS controls */ 5200 if (conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_ENABLE) { 5201 mpls_control_reg |= (1U << 7) | (1U << 3); 5202 } 5203 5204 if (conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_ENTROPY_ENABLE) { 5205 mpls_control_reg |= (1U << 6) | (1U << 2); 5206 } 5207 5208 if (conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_SPECIAL_LABEL_ENABLE) { 5209 mpls_control_reg |= (1U << 4); 5210 } 5211 5212 if (conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_CONTROL_WORD_ENABLE) { 5213 mpls_control_reg |= (1U << 5) | (1U << 1); 5214 } 5215 5216 SOC_IF_ERROR_RETURN 5217 (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc651, mpls_control_reg, 5218 (1U << 7) | (1U << 3)| (1U << 6) | (1U << 2) | (1U << 4) | (1U << 5) | (1U << 1))); 5219 5220 /* special label [19:16] */ 5221 SOC_IF_ERROR_RETURN 5222 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc653, (uint16)((conf->mpls_control.special_label >> 16 ) & 0xf))); 5223 5224 /* special label [15:0] */ 5225 SOC_IF_ERROR_RETURN 5226 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc652, (uint16)(conf->mpls_control.special_label & 0xffff))); 5227 5228 for (i = 0; i < 10; i++ ) { 5229 SOC_IF_ERROR_RETURN 5230 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc654 + i, (uint16)(conf->mpls_control.labels[i].value & 0xffff))); 5231 SOC_IF_ERROR_RETURN 5232 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc661 + i, (uint16)(conf->mpls_control.labels[i].mask & 0xffff))); 5233 } 5234 5235 SOC_IF_ERROR_RETURN 5236 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc65e, (uint16)( 5237 ((conf->mpls_control.labels[3].value >> 4) & 0xf000) | 5238 ((conf->mpls_control.labels[2].value >> 8) & 0x0f00) | 5239 ((conf->mpls_control.labels[1].value >> 12) & 0x00f0) | 5240 ((conf->mpls_control.labels[0].value >> 16) & 0x000f)))); 5241 5242 SOC_IF_ERROR_RETURN 5243 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc65f, (uint16)( 5244 ((conf->mpls_control.labels[7].value >> 4) & 0xf000) | 5245 ((conf->mpls_control.labels[6].value >> 8) & 0x0f00) | 5246 ((conf->mpls_control.labels[5].value >> 12) & 0x00f0) | 5247 ((conf->mpls_control.labels[4].value >> 16) & 0x000f)))); 5248 5249 SOC_IF_ERROR_RETURN 5250 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc660, (uint16)( 5251 ((conf->mpls_control.labels[9].value >> 12) & 0x00f0) | 5252 ((conf->mpls_control.labels[8].value >> 16) & 0x000f)))); 5253 5254 SOC_IF_ERROR_RETURN 5255 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc66b, (uint16)( 5256 ((conf->mpls_control.labels[3].mask >> 4) & 0xf000) | 5257 ((conf->mpls_control.labels[2].mask >> 8) & 0x0f00) | 5258 ((conf->mpls_control.labels[1].mask >> 12) & 0x00f0) | 5259 ((conf->mpls_control.labels[0].mask >> 16) & 0x000f)))); 5260 5261 SOC_IF_ERROR_RETURN 5262 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc66c, (uint16)( 5263 ((conf->mpls_control.labels[7].mask >> 4) & 0xf000) | 5264 ((conf->mpls_control.labels[6].mask >> 8) & 0x0f00) | 5265 ((conf->mpls_control.labels[5].mask >> 12) & 0x00f0) | 5266 ((conf->mpls_control.labels[4].mask >> 16) & 0x000f)))); 5267 5268 SOC_IF_ERROR_RETURN 5269 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc66d, (uint16)( 5270 ((conf->mpls_control.labels[9].mask >> 12) & 0x00f0) | 5271 ((conf->mpls_control.labels[8].mask >> 16) & 0x000f)))); 5272 5273 /* label flags */ 5274 temp = 0; 5275 for (i = 0; i < 8; i++ ) { 5276 temp |= conf->mpls_control.labels[i].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT ? (0x2 << (i<<1)) : 0; 5277 temp |= (conf->mpls_control.labels[i].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN) ? (0x1 << (i<<1)) : 0; 5278 } 5279 5280 SOC_IF_ERROR_RETURN 5281 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc66e, temp)); 5282 5283 temp = 0; 5284 for (i = 0; i < 2; i++ ) { 5285 temp |= (conf->mpls_control.labels[i + 8].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT) ? (0x2 << (i<<1)) : 0; 5286 temp |= (conf->mpls_control.labels[i + 8].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN) ? (0x1 << (i<<1)) : 0; 5287 } 5288 5289 SOC_IF_ERROR_RETURN 5290 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc66f, temp)); 5291 } 5292 5293 5294 return SOC_E_NONE; 5295 } 5296 5297 int 5298 phy_84728_timesync_config_get(int unit, soc_port_t port, soc_port_phy_timesync_config_t *conf) 5299 { 5300 uint16 rx_tx_control_reg = 0, tx_control_reg = 0, 5301 en_control_reg = 0, capture_en_reg = 0, 5302 nse_sc_8 = 0, nse_nco_3 = 0, temp1, temp2, temp3, value, mpls_control_reg; 5303 soc_port_phy_timesync_global_mode_t gmode = SOC_PORT_PHY_TIMESYNC_MODE_FREE; 5304 soc_port_phy_timesync_framesync_mode_t framesync_mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_NONE; 5305 soc_port_phy_timesync_syncout_mode_t syncout_mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE; 5306 int i; 5307 phy_ctrl_t *pc; 5308 5309 pc = EXT_PHY_SW_STATE(unit, port); 5310 5311 conf->flags = 0; 5312 5313 /* NSE SC 8 register */ 5314 SOC_IF_ERROR_RETURN 5315 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc63a, &nse_sc_8)); 5316 5317 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) { 5318 /* SLICE ENABLE CONTROL register */ 5319 SOC_IF_ERROR_RETURN 5320 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc600, &en_control_reg)); 5321 5322 if (en_control_reg & 1U) { 5323 conf->flags |= SOC_PORT_PHY_TIMESYNC_ENABLE; 5324 } 5325 5326 /* TXRX SOP TS CAPTURE ENABLE reg */ 5327 SOC_IF_ERROR_RETURN 5328 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc607, &capture_en_reg)); 5329 5330 if (capture_en_reg & 1U) { 5331 conf->flags |= SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE; 5332 } 5333 5334 /* NSE SC 8 register */ 5335 /* SOC_IF_ERROR_RETURN 5336 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc63a, &nse_sc_8)); 5337 */ 5338 5339 if (nse_sc_8 & (1U << 13)) { 5340 conf->flags |= SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE; 5341 } 5342 5343 /* RX TX CONTROL register */ 5344 SOC_IF_ERROR_RETURN 5345 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc61c, &rx_tx_control_reg)); 5346 5347 if (rx_tx_control_reg & (1U << 3)) { 5348 conf->flags |= SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE; 5349 } 5350 5351 /* TX CONTROL register */ 5352 SOC_IF_ERROR_RETURN 5353 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc618, &tx_control_reg)); 5354 5355 if (tx_control_reg & (1U << 3)) { 5356 conf->flags |= SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE; 5357 } 5358 5359 if (tx_control_reg & (1U << 2)) { 5360 conf->flags |= SOC_PORT_PHY_TIMESYNC_L2_ENABLE; 5361 } 5362 5363 if (tx_control_reg & (1U << 1)) { 5364 conf->flags |= SOC_PORT_PHY_TIMESYNC_IP4_ENABLE; 5365 } 5366 5367 if (tx_control_reg & (1U << 0)) { 5368 conf->flags |= SOC_PORT_PHY_TIMESYNC_IP6_ENABLE; 5369 } 5370 5371 SOC_IF_ERROR_RETURN 5372 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc630, &nse_nco_3)); 5373 5374 if (!(nse_nco_3 & (1U << 14))) { 5375 conf->flags |= SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT; 5376 } 5377 } 5378 5379 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) { 5380 _phy_84728_decode_gmode((nse_sc_8 >> 14),&gmode); 5381 conf->gmode = gmode; 5382 } 5383 5384 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) { 5385 _phy_84728_decode_framesync_mode((nse_sc_8 >> 2), &framesync_mode); 5386 conf->framesync.mode = framesync_mode; 5387 SOC_IF_ERROR_RETURN 5388 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc63c, &temp1)); 5389 SOC_IF_ERROR_RETURN 5390 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc63b, &temp2)); 5391 5392 /* Multiply by 6.4 without floating point */ 5393 conf->framesync.length_threshold = (temp1 * 64) / 10; 5394 conf->framesync.event_offset = (temp2 * 64) / 10; 5395 } 5396 5397 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) { 5398 _phy_84728_decode_syncout_mode((nse_sc_8 >> 0), &syncout_mode); 5399 conf->syncout.mode = syncout_mode; 5400 5401 SOC_IF_ERROR_RETURN 5402 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc635, &temp1)); 5403 SOC_IF_ERROR_RETURN 5404 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc634, &temp2)); 5405 SOC_IF_ERROR_RETURN 5406 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc633, &temp3)); 5407 5408 /* Multiply by 6.4 without floating point */ 5409 conf->syncout.pulse_1_length = (((temp3 >> 7) & 0x1ff) * 64) / 10; 5410 conf->syncout.pulse_2_length = ((((temp3 & 0x7f) << 2) | ((temp2 >> 14) & 0x3)) * 64) / 10; 5411 conf->syncout.interval = ((((temp2 & 0x3fff) << 16) | temp1) * 64) / 10; 5412 5413 SOC_IF_ERROR_RETURN 5414 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc639, &temp1)); 5415 SOC_IF_ERROR_RETURN 5416 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc638, &temp2)); 5417 SOC_IF_ERROR_RETURN 5418 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc637, &temp3)); 5419 5420 COMPILER_64_SET(conf->syncout.syncout_ts, ((uint32)temp3), (((uint32)temp2<<16)|((uint32)temp1))); 5421 } 5422 5423 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) { 5424 /* VLAN TAG register */ 5425 SOC_IF_ERROR_RETURN 5426 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc61d, &conf->itpid)); 5427 } 5428 5429 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) { 5430 /* OUTER VLAN TAG register */ 5431 SOC_IF_ERROR_RETURN 5432 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc61e, &conf->otpid)); 5433 } 5434 5435 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) { 5436 /* INNER VLAN TAG register */ 5437 SOC_IF_ERROR_RETURN 5438 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc61f, &conf->otpid2)); 5439 } 5440 5441 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) { 5442 SOC_IF_ERROR_RETURN 5443 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc636, &conf->ts_divider)); 5444 conf->ts_divider &= 0xfff; 5445 } 5446 5447 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) { 5448 SOC_IF_ERROR_RETURN 5449 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc605, &temp1)); 5450 SOC_IF_ERROR_RETURN 5451 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc606, &temp2)); 5452 5453 conf->rx_link_delay = ((uint32)temp2 << 16) | temp1; 5454 } 5455 5456 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) { 5457 /* TIME CODE 5 register */ 5458 SOC_IF_ERROR_RETURN 5459 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc610, &temp1)); 5460 5461 /* TIME CODE 4 register */ 5462 SOC_IF_ERROR_RETURN 5463 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc60f, &temp2)); 5464 5465 conf->original_timecode.nanoseconds = ((uint32)temp2 << 16) | temp1; 5466 5467 /* TIME CODE 3 register */ 5468 SOC_IF_ERROR_RETURN 5469 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc60e, &temp1)); 5470 5471 /* TIME CODE 2 register */ 5472 SOC_IF_ERROR_RETURN 5473 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc60d, &temp2)); 5474 5475 /* TIME CODE 1 register */ 5476 SOC_IF_ERROR_RETURN 5477 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc60c, &temp3)); 5478 5479 /* conf->original_timecode.seconds = ((uint64)temp3 << 32) | ((uint32)temp2 << 16) | temp1; */ 5480 5481 COMPILER_64_SET(conf->original_timecode.seconds, ((uint32)temp3), (((uint32)temp2<<16)|((uint32)temp1))); 5482 } 5483 5484 /* Tx/Rx TS Offset */ 5485 if (conf->validity_mask & (SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET | 5486 SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET)) { 5487 /* MSB [19:16] of Tx/Rx TS Offset */ 5488 SOC_IF_ERROR_RETURN 5489 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc67b, &temp1)); 5490 } 5491 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) { 5492 /* RX_TS_Offset[19:0] = (1.0xC67B[7:4]) | (1.0xC60B[15:0]) */ 5493 SOC_IF_ERROR_RETURN 5494 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc60b, &temp2)); 5495 conf->rx_timestamp_offset = (((uint32)(temp1 & 0xf0)) << 12) | temp2; 5496 } 5497 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) { 5498 /* TX_TS_Offset[19:0] = (1.0xC67B[3:0]) | (1.0xC60A[15:0]) */ 5499 SOC_IF_ERROR_RETURN 5500 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc60a, &temp2)); 5501 conf->rx_timestamp_offset = (((uint32)(temp1 & 0x0f)) << 16) | temp2; 5502 } 5503 5504 /* TX EVENT MESSAGE MODE SEL register */ 5505 SOC_IF_ERROR_RETURN 5506 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc601, &value)); 5507 5508 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) { 5509 _phy_84728_decode_egress_message_mode(value, 0, &conf->tx_sync_mode); 5510 } 5511 5512 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) { 5513 _phy_84728_decode_egress_message_mode(value, 2, &conf->tx_delay_request_mode); 5514 } 5515 5516 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) { 5517 _phy_84728_decode_egress_message_mode(value, 4, &conf->tx_pdelay_request_mode); 5518 } 5519 5520 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) { 5521 _phy_84728_decode_egress_message_mode(value, 6, &conf->tx_pdelay_response_mode); 5522 } 5523 5524 /* RX EVENT MESSAGE MODE SEL register */ 5525 SOC_IF_ERROR_RETURN 5526 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc603, &value)); 5527 5528 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) { 5529 _phy_84728_decode_ingress_message_mode(value, 0, &conf->rx_sync_mode); 5530 } 5531 5532 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) { 5533 _phy_84728_decode_ingress_message_mode(value, 2, &conf->rx_delay_request_mode); 5534 } 5535 5536 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) { 5537 _phy_84728_decode_ingress_message_mode(value, 4, &conf->rx_pdelay_request_mode); 5538 } 5539 5540 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) { 5541 _phy_84728_decode_ingress_message_mode(value, 6, &conf->rx_pdelay_response_mode); 5542 } 5543 5544 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) { 5545 /* Initial ref phase [15:0] */ 5546 SOC_IF_ERROR_RETURN 5547 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc623, &temp1)); 5548 5549 /* Initial ref phase [31:16] */ 5550 SOC_IF_ERROR_RETURN 5551 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc622, &temp2)); 5552 5553 /* Initial ref phase [47:32] */ 5554 SOC_IF_ERROR_RETURN 5555 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc621, &temp3)); 5556 5557 /* conf->phy_1588_dpll_phase_initial = ((uint64)temp3 << 32) | ((uint32)temp2 << 16) | temp1; */ 5558 5559 COMPILER_64_SET(conf->phy_1588_dpll_ref_phase, ((uint32)temp3), (((uint32)temp2<<16)|((uint32)temp1))); 5560 } 5561 5562 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) { 5563 SOC_IF_ERROR_RETURN 5564 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc625, &temp1)); 5565 SOC_IF_ERROR_RETURN 5566 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc624, &temp2)); 5567 5568 conf->phy_1588_dpll_ref_phase_delta = ((uint32)temp2 << 16) | temp1; 5569 } 5570 5571 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) { 5572 /* DPLL K1 */ 5573 SOC_IF_ERROR_RETURN 5574 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc626, &conf->phy_1588_dpll_k1)); 5575 conf->phy_1588_dpll_k1 &= 0xff; 5576 } 5577 5578 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) { 5579 /* DPLL K2 */ 5580 SOC_IF_ERROR_RETURN 5581 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc627, &conf->phy_1588_dpll_k2)); 5582 conf->phy_1588_dpll_k2 &= 0xff; 5583 } 5584 5585 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) { 5586 /* DPLL K3 */ 5587 SOC_IF_ERROR_RETURN 5588 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc628, &conf->phy_1588_dpll_k3)); 5589 conf->phy_1588_dpll_k3 &= 0xff; 5590 } 5591 5592 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL) { 5593 SOC_IF_ERROR_RETURN 5594 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc651, &mpls_control_reg)); 5595 5596 conf->mpls_control.flags = 0; 5597 5598 if (mpls_control_reg & (1U << 7)) { 5599 conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_ENABLE; 5600 } 5601 5602 if (mpls_control_reg & (1U << 6)) { 5603 conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_ENTROPY_ENABLE; 5604 } 5605 5606 if (mpls_control_reg & (1U << 4)) { 5607 conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_SPECIAL_LABEL_ENABLE; 5608 } 5609 5610 if (mpls_control_reg & (1U << 5)) { 5611 conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_CONTROL_WORD_ENABLE; 5612 } 5613 5614 /* special label [19:16] */ 5615 SOC_IF_ERROR_RETURN 5616 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc653, &temp2)); 5617 5618 /* special label [15:0] */ 5619 SOC_IF_ERROR_RETURN 5620 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc652, &temp1)); 5621 5622 conf->mpls_control.special_label = ((uint32)(temp2 & 0x0f) << 16) | temp1; 5623 5624 5625 for (i = 0; i < 10; i++ ) { 5626 5627 SOC_IF_ERROR_RETURN 5628 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc654 + i, &temp1)); 5629 conf->mpls_control.labels[i].value = temp1; 5630 5631 SOC_IF_ERROR_RETURN 5632 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc661 + i, &temp1)); 5633 conf->mpls_control.labels[i].mask = temp1; 5634 } 5635 5636 /* now get [19:16] of labels */ 5637 SOC_IF_ERROR_RETURN 5638 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc65e, &temp1)); 5639 5640 conf->mpls_control.labels[0].value |= ((uint32)(temp1 & 0x000f) << 16); 5641 conf->mpls_control.labels[1].value |= ((uint32)(temp1 & 0x00f0) << 12); 5642 conf->mpls_control.labels[2].value |= ((uint32)(temp1 & 0x0f00) << 8); 5643 conf->mpls_control.labels[3].value |= ((uint32)(temp1 & 0xf000) << 4); 5644 5645 5646 SOC_IF_ERROR_RETURN 5647 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc65f, &temp1)); 5648 5649 conf->mpls_control.labels[4].value |= ((uint32)(temp1 & 0x000f) << 16); 5650 conf->mpls_control.labels[5].value |= ((uint32)(temp1 & 0x00f0) << 12); 5651 conf->mpls_control.labels[6].value |= ((uint32)(temp1 & 0x0f00) << 8); 5652 conf->mpls_control.labels[7].value |= ((uint32)(temp1 & 0xf000) << 4); 5653 5654 5655 SOC_IF_ERROR_RETURN 5656 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc660, &temp1)); 5657 5658 conf->mpls_control.labels[8].value |= ((uint32)(temp1 & 0x000f) << 16); 5659 conf->mpls_control.labels[9].value |= ((uint32)(temp1 & 0x00f0) << 12); 5660 5661 /* now get [19:16] of masks */ 5662 SOC_IF_ERROR_RETURN 5663 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc66b, &temp1)); 5664 5665 conf->mpls_control.labels[0].mask |= ((uint32)(temp1 & 0x000f) << 16); 5666 conf->mpls_control.labels[1].mask |= ((uint32)(temp1 & 0x00f0) << 12); 5667 conf->mpls_control.labels[2].mask |= ((uint32)(temp1 & 0x0f00) << 8); 5668 conf->mpls_control.labels[3].mask |= ((uint32)(temp1 & 0xf000) << 4); 5669 5670 5671 SOC_IF_ERROR_RETURN 5672 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc66c, &temp1)); 5673 5674 conf->mpls_control.labels[4].mask |= ((uint32)(temp1 & 0x000f) << 16); 5675 conf->mpls_control.labels[5].mask |= ((uint32)(temp1 & 0x00f0) << 12); 5676 conf->mpls_control.labels[6].mask |= ((uint32)(temp1 & 0x0f00) << 8); 5677 conf->mpls_control.labels[7].mask |= ((uint32)(temp1 & 0xf000) << 4); 5678 5679 5680 SOC_IF_ERROR_RETURN 5681 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc66d, &temp1)); 5682 5683 conf->mpls_control.labels[8].mask |= ((uint32)(temp1 & 0x000f) << 16); 5684 conf->mpls_control.labels[9].mask |= ((uint32)(temp1 & 0x00f0) << 12); 5685 5686 5687 /* label flags */ 5688 SOC_IF_ERROR_RETURN 5689 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc66e, &temp1)); 5690 for (i = 0; i < 8; i++ ) { 5691 conf->mpls_control.labels[i].flags |= temp1 & (0x2 << (i<<1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT : 0; 5692 conf->mpls_control.labels[i].flags |= temp1 & (0x1 << (i<<1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN : 0; 5693 } 5694 SOC_IF_ERROR_RETURN 5695 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc66f, &temp2)); 5696 for (i = 0; i < 2; i++ ) { 5697 conf->mpls_control.labels[i + 8].flags |= temp2 & (0x2 << (i<<1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT : 0; 5698 conf->mpls_control.labels[i + 8].flags |= temp2 & (0x1 << (i<<1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN : 0; 5699 } 5700 5701 } 5702 return SOC_E_NONE; 5703 } 5704 5705 int 5706 phy_84728_timesync_control_set(int unit, soc_port_t port, soc_port_control_phy_timesync_t type, uint64 value) 5707 { 5708 uint16 temp1, temp2; 5709 uint32 value0; 5710 phy_ctrl_t *pc; 5711 5712 pc = EXT_PHY_SW_STATE(unit, port); 5713 5714 switch (type) { 5715 5716 case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP: 5717 case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP: 5718 return SOC_E_FAIL; 5719 5720 5721 case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND: 5722 SOC_IF_ERROR_RETURN 5723 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc62f, (uint16)(COMPILER_64_LO(value) & 0xffff))); 5724 SOC_IF_ERROR_RETURN 5725 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc62e, (uint16)((COMPILER_64_LO(value) >> 16) & 0xffff))); 5726 break; 5727 5728 case SOC_PORT_CONTROL_PHY_TIMESYNC_FRAMESYNC: 5729 5730 SOC_IF_ERROR_RETURN 5731 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc63a, &temp1)); 5732 temp2 = ((temp1 | (0x3 << 14) | (0x1 << 12)) & ~(0xf << 2)) | (0x1 << 5); 5733 SOC_IF_ERROR_RETURN 5734 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63a, temp2)); 5735 sal_usleep(1); 5736 temp2 &= ~((0x1 << 5) | (0x1 << 12)); 5737 SOC_IF_ERROR_RETURN 5738 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63a, temp2)); 5739 sal_usleep(1); 5740 SOC_IF_ERROR_RETURN 5741 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63a, temp1)); 5742 break; 5743 5744 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME: 5745 COMPILER_64_SHR(value, 4); 5746 SOC_IF_ERROR_RETURN 5747 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc632, (uint16)(COMPILER_64_LO(value) & 0xffff))); 5748 SOC_IF_ERROR_RETURN 5749 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc631, (uint16)((COMPILER_64_LO(value) >> 16) & 0xffff))); 5750 SOC_IF_ERROR_RETURN 5751 (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc630, (uint16)(COMPILER_64_HI(value) & 0xfff), 0x0fff)); 5752 break; 5753 5754 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL: 5755 temp1 = 0; 5756 temp2 = 0; 5757 5758 value0 = COMPILER_64_LO(value); 5759 5760 if (value0 & SOC_PORT_PHY_TIMESYNC_TN_LOAD) { 5761 temp1 |= 1U << 11; 5762 } 5763 if (value0 & SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD) { 5764 temp2 |= 1U << 11; 5765 } 5766 if (value0 & SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD) { 5767 temp1 |= 1U << 10; 5768 } 5769 if (value0 & SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD) { 5770 temp2 |= 1U << 10; 5771 } 5772 if (value0 & SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD) { 5773 temp1 |= 1U << 9; 5774 } 5775 if (value0 & SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD) { 5776 temp2 |= 1U << 9; 5777 } 5778 if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD) { 5779 temp1 |= 1U << 8; 5780 } 5781 if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD) { 5782 temp2 |= 1U << 8; 5783 } 5784 if (value0 & SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD) { 5785 temp1 |= 1U << 7; 5786 } 5787 if (value0 & SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD) { 5788 temp2 |= 1U << 7; 5789 } 5790 if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD) { 5791 temp1 |= 1U << 6; 5792 } 5793 if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD) { 5794 temp2 |= 1U << 6; 5795 } 5796 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD) { 5797 temp1 |= 1U << 5; 5798 } 5799 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD) { 5800 temp2 |= 1U << 5; 5801 } 5802 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD) { 5803 temp1 |= 1U << 4; 5804 } 5805 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD) { 5806 temp2 |= 1U << 4; 5807 } 5808 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD) { 5809 temp1 |= 1U << 3; 5810 } 5811 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD) { 5812 temp2 |= 1U << 3; 5813 } 5814 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD) { 5815 temp1 |= 1U << 2; 5816 } 5817 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD) { 5818 temp2 |= 1U << 2; 5819 } 5820 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD) { 5821 temp1 |= 1U << 1; 5822 } 5823 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD) { 5824 temp2 |= 1U << 1; 5825 } 5826 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD) { 5827 temp1 |= 1U << 0; 5828 } 5829 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD) { 5830 temp2 |= 1U << 0; 5831 } 5832 SOC_IF_ERROR_RETURN 5833 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc615, temp1)); 5834 5835 /* always load not supported at the moment */ 5836 /* 5837 SOC_IF_ERROR_RETURN 5838 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc615, temp2)); 5839 */ 5840 5841 break; 5842 5843 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT: 5844 temp1 = 0; 5845 5846 value0 = COMPILER_64_LO(value); 5847 5848 if (value0 & SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT) { 5849 temp1 |= 1U << 1; 5850 } 5851 if (value0 & SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT) { 5852 temp1 |= 1U << 0; 5853 } 5854 SOC_IF_ERROR_RETURN 5855 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc617, temp1)); 5856 break; 5857 5858 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK: 5859 temp1 = 0; 5860 5861 value0 = COMPILER_64_LO(value); 5862 5863 if (value0 & SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT_MASK) { 5864 temp1 |= 1U << 1; 5865 } 5866 if (value0 & SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT_MASK) { 5867 temp1 |= 1U << 0; 5868 } 5869 SOC_IF_ERROR_RETURN 5870 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc616, temp1)); 5871 break; 5872 5873 case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET: 5874 value0 = COMPILER_64_LO(value); 5875 /* TX_TS_Offset[19:0] = (1.0xC67B[3:0]) | (1.0xC60A[15:0]) */ 5876 SOC_IF_ERROR_RETURN 5877 (BSDK_WR_PHY84728_LN_DEV1_PMDr( pc, 0xc60a, 5878 (uint16) ( value0 & 0x0ffff)) ); 5879 SOC_IF_ERROR_RETURN 5880 (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc67b, 5881 (uint16) (((value0 & 0xf0000)) >> 16), (0xf << 0)) ); 5882 break; 5883 5884 case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET: 5885 value0 = COMPILER_64_LO(value); 5886 /* RX_TS_Offset[19:0] = (1.0xC67B[7:4]) | (1.0xC60B[15:0]) */ 5887 SOC_IF_ERROR_RETURN 5888 (BSDK_WR_PHY84728_LN_DEV1_PMDr( pc, 0xc60b, 5889 (uint16) ( value0 & 0x0ffff)) ); 5890 SOC_IF_ERROR_RETURN 5891 (BSDK_MOD_PHY84728_LN_DEV1_PMDr(pc, 0xc67b, 5892 (uint16) (((value0 & 0xf0000)) >> 12), (0xf << 4)) ); 5893 break; 5894 5895 default: 5896 return SOC_E_NONE; 5897 break; 5898 } 5899 5900 return SOC_E_NONE; 5901 } 5902 5903 int 5904 phy_84728_timesync_control_get(int unit, soc_port_t port, soc_port_control_phy_timesync_t type, uint64 *value) 5905 { 5906 uint16 value0 = 0; 5907 uint16 value1 = 0; 5908 uint16 value2 = 0; 5909 uint32 value4 = 0; 5910 phy_ctrl_t *pc; 5911 5912 pc = EXT_PHY_SW_STATE(unit, port); 5913 5914 switch (type) { 5915 case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP: 5916 5917 SOC_IF_ERROR_RETURN 5918 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63d, 0x4)); 5919 5920 SOC_IF_ERROR_RETURN 5921 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc647, &value0)); 5922 SOC_IF_ERROR_RETURN 5923 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc646, &value1)); 5924 SOC_IF_ERROR_RETURN 5925 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc645, &value2)); 5926 5927 SOC_IF_ERROR_RETURN 5928 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63d, 0x8)); 5929 SOC_IF_ERROR_RETURN 5930 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63d, 0x0)); 5931 5932 /* *value = (((uint64)value3) << 48) | (((uint64)value2) << 32) | (((uint64)value1) << 16) | ((uint64)value0); */ 5933 COMPILER_64_SET((*value), ((uint32)value2), (((uint32)value1<<16)|((uint32)value0))); 5934 5935 break; 5936 5937 case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP: 5938 5939 SOC_IF_ERROR_RETURN 5940 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63d, 0x1)); 5941 5942 SOC_IF_ERROR_RETURN 5943 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc640, &value0)); 5944 SOC_IF_ERROR_RETURN 5945 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc63f, &value1)); 5946 SOC_IF_ERROR_RETURN 5947 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc63e, &value2)); 5948 5949 SOC_IF_ERROR_RETURN 5950 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63d, 0x2)); 5951 SOC_IF_ERROR_RETURN 5952 (BSDK_WR_PHY84728_LN_DEV1_PMDr(pc, 0xc63d, 0x0)); 5953 5954 /* *value = (((uint64)value3) << 48) | (((uint64)value2) << 32) | (((uint64)value1) << 16) | ((uint64)value0); */ 5955 COMPILER_64_SET((*value), ((uint32)value2), (((uint32)value1<<16)|((uint32)value0))); 5956 break; 5957 5958 case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND: 5959 SOC_IF_ERROR_RETURN 5960 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc62f, &value0)); 5961 SOC_IF_ERROR_RETURN 5962 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc62e, &value1)); 5963 COMPILER_64_SET((*value), 0, (((uint32)value1<<16)|((uint32)value0))); 5964 break; 5965 5966 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME: 5967 SOC_IF_ERROR_RETURN 5968 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc632, &value0)); 5969 SOC_IF_ERROR_RETURN 5970 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc631, &value1)); 5971 SOC_IF_ERROR_RETURN 5972 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc630, &value2)); 5973 COMPILER_64_SET((*value), ((uint32)(value2 & 0x0fff)), (((uint32)value1<<16)|((uint32)value0))); 5974 COMPILER_64_SHL((*value), 4); 5975 break; 5976 5977 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL: 5978 5979 SOC_IF_ERROR_RETURN 5980 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc615, &value1)); 5981 /* always load not supported at the moment */ 5982 /* 5983 SOC_IF_ERROR_RETURN 5984 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc615, &value2)); 5985 */ 5986 5987 value4 = 0; 5988 5989 if (value1 & (1U << 11)) { 5990 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_TN_LOAD; 5991 } 5992 #if 0 5993 if (value2 & (1U << 11)) { 5994 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD; 5995 } 5996 #endif 5997 if (value1 & (1U << 10)) { 5998 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD; 5999 } 6000 #if 0 6001 if (value2 & (1U << 10)) { 6002 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD; 6003 } 6004 #endif 6005 if (value1 & (1U << 9)) { 6006 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD; 6007 } 6008 #if 0 6009 if (value2 & (1U << 9)) { 6010 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD; 6011 } 6012 #endif 6013 if (value1 & (1U << 8)) { 6014 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD; 6015 } 6016 if (value1 & (1U << 8)) { 6017 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD; 6018 } 6019 if (value1 & (1U << 7)) { 6020 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD; 6021 } 6022 if (value1 & (1U << 7)) { 6023 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD; 6024 } 6025 if (value1 & (1U << 6)) { 6026 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD; 6027 } 6028 #if 0 6029 if (value2 & (1U << 6)) { 6030 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD; 6031 } 6032 #endif 6033 if (value1 & (1U << 5)) { 6034 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD; 6035 } 6036 #if 0 6037 if (value2 & (1U << 5)) { 6038 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD; 6039 } 6040 #endif 6041 if (value1 & (1U << 4)) { 6042 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD; 6043 } 6044 #if 0 6045 if (value2 & (1U << 4)) { 6046 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD; 6047 } 6048 #endif 6049 if (value1 & (1U << 3)) { 6050 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD; 6051 } 6052 #if 0 6053 if (value2 & (1U << 3)) { 6054 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD; 6055 } 6056 #endif 6057 if (value1 & (1U << 2)) { 6058 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD; 6059 } 6060 #if 0 6061 if (value2 & (1U << 2)) { 6062 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD; 6063 } 6064 #endif 6065 if (value1 & (1U << 1)) { 6066 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD; 6067 } 6068 #if 0 6069 if (value2 & (1U << 1)) { 6070 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD; 6071 } 6072 #endif 6073 if (value1 & (1U << 0)) { 6074 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD; 6075 } 6076 #if 0 6077 if (value2 & (1U << 0)) { 6078 value4 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD; 6079 } 6080 #endif 6081 COMPILER_64_SET((*value), 0, value4); 6082 6083 break; 6084 6085 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT: 6086 SOC_IF_ERROR_RETURN 6087 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc617, &value1)); 6088 6089 value0 = 0; 6090 6091 if (value1 & (1U << 1)) { 6092 value0 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT; 6093 } 6094 if (value1 & (1U << 0)) { 6095 value0 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT; 6096 } 6097 COMPILER_64_SET((*value), 0, (uint32)value0); 6098 6099 break; 6100 6101 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK: 6102 SOC_IF_ERROR_RETURN 6103 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc616, &value1)); 6104 6105 value0 = 0; 6106 6107 if (value1 & (1U << 1)) { 6108 value0 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT_MASK; 6109 } 6110 if (value1 & (1U << 0)) { 6111 value0 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT_MASK; 6112 } 6113 COMPILER_64_SET((*value), 0, (uint32)value0); 6114 6115 break; 6116 6117 case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET: 6118 /* MSB [19:16] of Tx TS Offset */ 6119 SOC_IF_ERROR_RETURN 6120 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc67b, &value1)); 6121 /* TX_TS_Offset[19:0] = (1.0xC67B[3:0]) | (1.0xC60A[15:0]) */ 6122 SOC_IF_ERROR_RETURN 6123 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc60a, &value0)); 6124 COMPILER_64_SET((*value), 0, 6125 (((uint32)(value1 & 0x0f)) << 16) | value0); 6126 break; 6127 6128 case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET: 6129 /* MSB [19:16] of Rx TS Offset */ 6130 SOC_IF_ERROR_RETURN 6131 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc67b, &value1)); 6132 /* RX_TS_Offset[19:0] = (1.0xC67B[7:4]) | (1.0xC60B[15:0]) */ 6133 SOC_IF_ERROR_RETURN 6134 (BSDK_RD_PHY84728_LN_DEV1_PMDr(pc, 0xc60b, &value0)); 6135 COMPILER_64_SET((*value), 0, 6136 (((uint32)(value1 & 0xf0)) << 12) | value0); 6137 break; 6138 6139 default: 6140 return SOC_E_FAIL; 6141 } 6142 6143 return SOC_E_NONE; 6144 } 6145 6146 int 6147 bsdk_phy84728_reg_read(phy_ctrl_t * pc, uint32 flags, uint8 reg_bank, 6148 uint16 reg_addr, uint16 *data) 6149 { 6150 int rv; 6151 #if 0 6152 uint16 reg_data, xpmd_reg_sel = 0xffff; 6153 #endif 6154 uint32 cl45_reg_addr; 6155 6156 rv = SOC_E_NONE; 6157 6158 #if 0 6159 if (flags & BSDK_PHY84728_SYS_SIDE) { 6160 /* Select System side registers */ 6161 cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(1, xpmd_reg_sel); 6162 reg_data = 0x01; 6163 SOC_IF_ERROR_RETURN( 6164 BSDK_PHY84728_IO_MDIO_WRITE(pc, cl45_reg_addr, reg_data)); 6165 6166 cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(reg_bank, reg_addr); 6167 rv = BSDK_PHY84728_IO_MDIO_READ(pc, cl45_reg_addr, data); 6168 6169 /* De-Select System side registers */ 6170 cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(1, xpmd_reg_sel); 6171 reg_data = 0x0; 6172 SOC_IF_ERROR_RETURN( 6173 BSDK_PHY84728_IO_MDIO_WRITE(pc, cl45_reg_addr, reg_data)); 6174 6175 } else { 6176 #endif 6177 { 6178 cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(reg_bank, reg_addr); 6179 rv = BSDK_PHY84728_IO_MDIO_READ(pc, cl45_reg_addr, data); 6180 } 6181 6182 return rv; 6183 } 6184 6185 int 6186 bsdk_phy84728_reg_write(phy_ctrl_t * pc, uint32 flags, uint8 reg_bank, 6187 uint16 reg_addr, uint16 data) 6188 { 6189 int rv; 6190 #if 0 6191 uint16 reg_data, xpmd_reg_sel = 0xffff; 6192 #endif 6193 uint32 cl45_reg_addr; 6194 6195 rv = SOC_E_NONE; 6196 6197 #if 0 6198 if (flags & BSDK_PHY84728_SYS_SIDE) { 6199 /* Select System side registers */ 6200 cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(1, xpmd_reg_sel); 6201 reg_data = 0x01; 6202 SOC_IF_ERROR_RETURN( 6203 BSDK_PHY84728_IO_MDIO_WRITE(pc, cl45_reg_addr, reg_data)); 6204 6205 cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(reg_bank, reg_addr); 6206 rv = BSDK_PHY84728_IO_MDIO_WRITE(pc, cl45_reg_addr, data); 6207 6208 /* De-Select System side registers */ 6209 cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(1, xpmd_reg_sel); 6210 reg_data = 0x00; 6211 SOC_IF_ERROR_RETURN( 6212 BSDK_PHY84728_IO_MDIO_WRITE(pc, cl45_reg_addr, reg_data)); 6213 6214 } else { 6215 #endif 6216 { 6217 cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(reg_bank, reg_addr); 6218 rv = BSDK_PHY84728_IO_MDIO_WRITE(pc, cl45_reg_addr, data); 6219 } 6220 6221 return rv; 6222 } 6223 6224 6225 int 6226 bsdk_phy84728_reg_modify(phy_ctrl_t * pc, uint32 flags, uint8 reg_bank, 6227 uint16 reg_addr, uint16 data, uint16 mask) 6228 { 6229 uint16 tmp, otmp, reg_data; 6230 uint32 cl45_reg_addr = 0; 6231 #if 0 6232 uint16 xpmd_reg_sel = 0xffff; 6233 #endif 6234 6235 #if 0 6236 if (flags & BSDK_PHY84728_SYS_SIDE) { 6237 /* Select System side registers */ 6238 cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(1, xpmd_reg_sel); 6239 reg_data = 0x01; 6240 SOC_IF_ERROR_RETURN( 6241 BSDK_PHY84728_IO_MDIO_WRITE(pc, cl45_reg_addr, reg_data)); 6242 6243 cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(reg_bank, reg_addr); 6244 6245 SOC_IF_ERROR_RETURN 6246 (BSDK_PHY84728_IO_MDIO_READ(pc, cl45_reg_addr, &tmp)); 6247 6248 reg_data = data & mask; /* Mask off other bits */ 6249 otmp = tmp; 6250 tmp &= ~(mask); 6251 tmp |= reg_data; 6252 6253 if (otmp != tmp) { 6254 SOC_IF_ERROR_RETURN 6255 (BSDK_PHY84728_IO_MDIO_WRITE(pc, cl45_reg_addr, tmp)); 6256 } 6257 6258 /* De-Select System side registers */ 6259 cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(1, xpmd_reg_sel); 6260 data = 0x00; 6261 SOC_IF_ERROR_RETURN( 6262 BSDK_PHY84728_IO_MDIO_WRITE(pc, cl45_reg_addr, data)); 6263 6264 } else { 6265 #endif 6266 { 6267 cl45_reg_addr = SOC_PHY_CLAUSE45_ADDR(reg_bank, reg_addr); 6268 6269 SOC_IF_ERROR_RETURN 6270 (BSDK_PHY84728_IO_MDIO_READ(pc, cl45_reg_addr, &tmp)); 6271 6272 reg_data = data & mask; /* Mask off other bits */ 6273 otmp = tmp; 6274 tmp &= ~(mask); 6275 tmp |= reg_data; 6276 6277 if (otmp != tmp) { 6278 SOC_IF_ERROR_RETURN 6279 (BSDK_PHY84728_IO_MDIO_WRITE(pc, cl45_reg_addr, tmp)); 6280 } 6281 } 6282 return SOC_E_NONE; 6283 } 6284 6285 /* 6286 * Variable: 6287 * phy_84728_drv 6288 * Purpose: 6289 * Phy Driver for BCM84728 PHY 6290 */ 6291 6292 phy_driver_t phy_84728drv_xe = { 6293 "84728 1G/10-Gigabit PHY Driver", 6294 phy_84728_init, /* Init */ 6295 phy_null_reset, /* Reset */ 6296 phy_84728_link_get, /* Link get */ 6297 phy_84728_enable_set, /* Enable set */ 6298 phy_null_enable_get, /* Enable get */ 6299 phy_84728_duplex_set, /* Duplex set */ 6300 phy_84728_duplex_get, /* Duplex get */ 6301 phy_84728_speed_set, /* Speed set */ 6302 phy_84728_speed_get, /* Speed get */ 6303 phy_84728_master_set, /* Master set */ 6304 phy_84728_master_get, /* Master get */ 6305 phy_84728_an_set, /* ANA set */ 6306 phy_84728_an_get, /* ANA get */ 6307 NULL, /* Local Advert set, deprecated */ 6308 NULL, /* Local Advert get, deprecated */ 6309 NULL, /* Remote Advert get, deprecated */ 6310 phy_84728_lb_set, /* PHY loopback set */ 6311 phy_84728_lb_get, /* PHY loopback set */ 6312 phy_null_interface_set, /* IO Interface set */ 6313 phy_84728_interface_get, /* IO Interface get */ 6314 NULL, /* pd_ability, deprecated */ 6315 phy_84728_link_up, 6316 phy_84728_link_down, 6317 phy_84728_mdix_set, /* phy_84728_mdix_set */ 6318 phy_84728_mdix_get, /* phy_84728_mdix_get */ 6319 phy_84728_mdix_status_get, /* phy_84728_mdix_status_get */ 6320 phy_84728_medium_config_set, /* medium config setting set */ 6321 phy_84728_medium_config_get, /* medium config setting get */ 6322 phy_84728_medium_status, /* active medium */ 6323 NULL, /* phy_cable_diag */ 6324 NULL, /* phy_link_change */ 6325 phy_84728_control_set, /* phy_control_set */ 6326 phy_84728_control_get, /* phy_control_get */ 6327 NULL, /* phy_reg_read */ 6328 NULL, /* phy_reg_write */ 6329 NULL, /* phy_reg_modify */ 6330 NULL, /* phy_notify */ 6331 phy_84728_probe, /* pd_probe */ 6332 phy_84728_ability_advert_set, /* pd_ability_advert_set */ 6333 phy_84728_ability_advert_get, /* pd_ability_advert_get */ 6334 phy_84728_ability_remote_get, /* pd_ability_remote_get */ 6335 phy_84728_ability_local_get, /* pd_ability_local_get */ 6336 phy_84728_firmware_set, 6337 phy_84728_timesync_config_set, 6338 phy_84728_timesync_config_get, 6339 phy_84728_timesync_control_set, 6340 phy_84728_timesync_control_get 6341 }; 6342 #else /* INCLUDE_PHY_84728 */ 6343 int _phy_84728_not_empty; 6344 #endif /* INCLUDE_PHY_84728 */