phy8703.c (9615B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: phy8703.c 8 * Purpose: Phys driver support for Broadcom Serial 10Gig 9 * transceiver with XAUI interface. 10 */ 11 12 13 #include <sal/types.h> 14 #include <sal/core/spl.h> 15 #include <shared/bsl.h> 16 #include <soc/drv.h> 17 #include <soc/debug.h> 18 #include <soc/error.h> 19 #include <soc/phyreg.h> 20 21 #include <soc/phy.h> 22 #include <soc/phy/phyctrl.h> 23 #include <soc/phy/drv.h> 24 25 #include "phydefs.h" /* Must include before other phy related includes */ 26 27 #ifdef INCLUDE_PHY_8703 28 #include "phyconfig.h" /* Must be the first phy include after phydefs.h */ 29 #include "phyident.h" 30 #include "phyreg.h" 31 #include "phynull.h" 32 #include "phyxehg.h" 33 #include "phy8703.h" 34 35 36 /* 37 * Function: 38 * phy_8703_init 39 * Purpose: 40 * Initialize 8703 phys 41 * Parameters: 42 * unit - StrataSwitch unit #. 43 * port - StrataSwitch port #. 44 * Returns: 45 * SOC_E_NONE 46 */ 47 48 static int 49 phy_8703_init(int unit, soc_port_t port) 50 { 51 int is_8704; 52 uint16 tmp; 53 phy_ctrl_t *pc; 54 55 pc = EXT_PHY_SW_STATE(unit, port); 56 57 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER | PHY_FLAGS_C45); 58 59 /* Reset the device */ 60 SOC_IF_ERROR_RETURN 61 (MODIFY_PHY8703_PMA_PMD_CTRLr(unit, pc, 62 MII_CTRL_RESET, MII_CTRL_RESET)); 63 64 SOC_IF_ERROR_RETURN 65 (MODIFY_PHY8703_PCS_CTRLr(unit, pc, 66 MII_CTRL_RESET, MII_CTRL_RESET)); 67 68 SOC_IF_ERROR_RETURN 69 (MODIFY_PHY8703_PHYXS_CTRLr(unit, pc, 70 MII_CTRL_RESET, MII_CTRL_RESET)); 71 72 73 /* P_DOWN/OPTXRST1 */ 74 SOC_IF_ERROR_RETURN 75 (READ_PHY8703_IDENTIFIERr(unit, pc, &tmp)); 76 77 if (soc_property_port_get(unit, port, spn_FORCE_OPTTXENBLVL, FALSE)) { 78 tmp |= 0x8000; /* Set OPTXENB_LVL */ 79 } else { 80 tmp &= ~0x8000; 81 } 82 83 if (soc_property_port_get(unit, port, spn_FORCE_OPTTXRSTLVL, TRUE)) { 84 tmp |= 0x4000; /* Set OPTXRST_LVL */ 85 } else { 86 tmp &= ~0x4000; 87 } 88 89 if (soc_property_port_get(unit, port, spn_FORCE_OPTBIASFLTLVL, TRUE)) { 90 tmp |= 0x2000; /* Set OPBIASFLT_LVL */ 91 } else { 92 tmp &= ~0x2000; 93 } 94 95 if (soc_property_port_get(unit, port, spn_FORCE_OPTTEMPFLTLVL, TRUE)) { 96 tmp |= 0x1000; /* Set OPMPFLT_LVL */ 97 } else { 98 tmp &= ~0x1000; 99 } 100 101 if (soc_property_port_get(unit, port, spn_FORCE_OPTPRFLTLVL, TRUE)) { 102 tmp |= 0x0800; /* Set OPPRFLT_LVL */ 103 } else { 104 tmp &= ~0x0800; 105 } 106 107 if (soc_property_port_get(unit, port, spn_FORCE_OPTTXFLLVL, TRUE)) { 108 tmp |= 0x0400; /* Set OPTXFLT_LVL */ 109 } else { 110 tmp &= ~0x0400; 111 } 112 113 if (soc_property_port_get(unit, port, spn_FORCE_OPTRXLOSLVL, TRUE)) { 114 tmp |= 0x0200; /* Set OPRXLOS_LVL */ 115 } else { 116 tmp &= ~0x0200; 117 } 118 119 if (soc_property_port_get(unit, port, spn_FORCE_OPTRXFLTLVL, TRUE)) { 120 tmp |= 0x0100; /* Set OPRXFLT_LVL */ 121 } else { 122 tmp &= ~0x0100; 123 } 124 125 if (soc_property_port_get(unit, port, spn_FORCE_OPTTXONLVL, TRUE)) { 126 tmp |= 0x0080; /* Set OPTXON_LVL */ 127 } else { 128 tmp &= ~0x0080; 129 } 130 131 SOC_IF_ERROR_RETURN 132 (WRITE_PHY8703_IDENTIFIERr(unit, pc, tmp)); 133 134 /* 135 * Enable 8704 XFP clock output 136 */ 137 is_8704 = pc->phy_rev == 3; 138 if (is_8704 && 139 soc_property_port_get(unit, port, spn_PHY_XFP_CLOCK, TRUE)) { 140 SOC_IF_ERROR_RETURN 141 (MODIFY_PHY8703_PMD_TX_CTRLr(unit, pc, 0x0100, 0x0100)); 142 } 143 144 LOG_INFO(BSL_LS_SOC_PHY, 145 (BSL_META_U(unit, 146 "8703: u=%d port%d: init.\n"), 147 unit, port)); 148 149 return SOC_E_NONE; 150 } 151 152 /* 153 * Function: 154 * phy_8703_link_get 155 * Purpose: 156 * Get layer2 connection status. 157 * Parameters: 158 * unit - StrataSwitch unit #. 159 * port - StrataSwitch port #. 160 * link - address of memory to store link up/down state. 161 * Returns: 162 * SOC_E_NONE 163 */ 164 165 STATIC int 166 phy_8703_link_get(int unit, soc_port_t port, int *link) 167 { 168 uint16 pma_mii_stat, pcs_mii_stat, pxs_mii_stat, link_stat; 169 phy_ctrl_t *pc; 170 171 LOG_INFO(BSL_LS_SOC_PHY, 172 (BSL_META_U(unit, 173 "phy_8703_link_get: u=%d port%d: link:%s\n"), 174 unit, port, "")); 175 176 if (link == NULL) { 177 return SOC_E_NONE; 178 } 179 180 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 181 *link = FALSE; 182 return SOC_E_NONE; 183 } 184 185 pc = EXT_PHY_SW_STATE(unit, port); 186 SOC_IF_ERROR_RETURN 187 (READ_PHY8703_PMA_PMD_STATr(unit, pc, &pma_mii_stat)); 188 189 /* Receive Link status */ 190 SOC_IF_ERROR_RETURN 191 (READ_PHY8703_PCS_STATr(unit, pc, &pcs_mii_stat)); 192 193 /* Transmit Link status */ 194 SOC_IF_ERROR_RETURN 195 (READ_PHY8703_PHYXS_STATr(unit, pc, &pxs_mii_stat)); 196 197 link_stat = pma_mii_stat & pcs_mii_stat & pxs_mii_stat; 198 199 *link = (link_stat & MII_STAT_LA) ? TRUE : FALSE; 200 201 LOG_INFO(BSL_LS_SOC_PHY, 202 (BSL_META_U(unit, 203 "phy_8703_link_get: u=%d port%d: link:%s\n"), 204 unit, port, *link ? "Up": "Down")); 205 206 return SOC_E_NONE; 207 } 208 209 /* 210 * Function: 211 * phy_8703_enable_set 212 * Purpose: 213 * Enable/Disable phy 214 * Parameters: 215 * unit - StrataSwitch unit #. 216 * port - StrataSwitch port #. 217 * enable - on/off state to set 218 * Returns: 219 * SOC_E_NONE 220 */ 221 222 STATIC int 223 phy_8703_enable_set(int unit, soc_port_t port, int enable) 224 { 225 uint16 data; /* Holder for new value to write to PHY reg */ 226 uint16 mask; /* Holder for bit mask to update in PHY reg */ 227 phy_ctrl_t *pc; 228 229 pc = EXT_PHY_SW_STATE(unit, port); 230 231 data = 0; 232 mask = 1 << 0; /* Global PMD transmit disable */ 233 if (enable) { 234 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE); 235 } else { 236 data = 1 << 0; /* Global PMD transmit disable */ 237 PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE); 238 } 239 240 SOC_IF_ERROR_RETURN 241 (MODIFY_PHY8703_PMA_PMD_TX_DISABLEr(unit, pc, data, mask)); 242 return (SOC_E_NONE); 243 } 244 245 246 /* 247 * Function: 248 * phy_8703_lb_set 249 * Purpose: 250 * Put 8703 in PHY PCS/PMA/PMD loopback 251 * Parameters: 252 * unit - StrataSwitch unit #. 253 * port - StrataSwitch port #. 254 * enable - binary value for on/off (1/0) 255 * Returns: 256 * SOC_E_NONE 257 */ 258 259 STATIC int 260 phy_8703_lb_set(int unit, soc_port_t port, int enable) 261 { 262 uint16 tmp; 263 phy_ctrl_t *pc; 264 265 LOG_INFO(BSL_LS_SOC_PHY, 266 (BSL_META_U(unit, 267 "phy_8703_lb_set: u=%d port%d: %s PCS/PMA/PMD loopback.\n"), 268 unit, port, enable ? "Enabling": "Disabling")); 269 270 pc = EXT_PHY_SW_STATE(unit, port); 271 272 tmp = enable ? MII_CTRL_PMA_LOOPBACK : 0; 273 274 SOC_IF_ERROR_RETURN 275 (MODIFY_PHY8703_PMA_PMD_CTRLr(unit, pc, 276 tmp, MII_CTRL_PMA_LOOPBACK)); 277 278 return SOC_E_NONE; 279 } 280 281 /* 282 * Function: 283 * phy_8703_lb_get 284 * Purpose: 285 * Get 8703 PHY loopback state 286 * Parameters: 287 * unit - StrataSwitch unit #. 288 * port - StrataSwitch port #. 289 * enable - address of location to store binary value for on/off (1/0) 290 * Returns: 291 * SOC_E_NONE 292 */ 293 294 STATIC int 295 phy_8703_lb_get(int unit, soc_port_t port, int *enable) 296 { 297 uint16 tmp; 298 phy_ctrl_t *pc; 299 300 pc = EXT_PHY_SW_STATE(unit, port); 301 SOC_IF_ERROR_RETURN 302 (READ_PHY8703_PMA_PMD_CTRLr(unit, pc, &tmp)); 303 304 *enable = (tmp & MII_CTRL_PMA_LOOPBACK) ? TRUE : FALSE; 305 306 LOG_INFO(BSL_LS_SOC_PHY, 307 (BSL_META_U(unit, 308 "phy_8703_lb_get: u=%d port%d: loopback:%s\n"), 309 unit, port, *enable ? "Enabled": "Disabled")); 310 311 return SOC_E_NONE; 312 } 313 314 315 /* 316 * Variable: 317 * phy_8703_drv 318 * Purpose: 319 * Phy Driver for 10G (XAUI x 4) Serdes PHY. 320 */ 321 322 phy_driver_t phy_8703drv_xe = { 323 "8703 10-Gigabit PHY Driver", 324 phy_8703_init, /* Init */ 325 phy_null_reset, /* Reset (dummy) */ 326 phy_8703_link_get, /* Link get */ 327 phy_8703_enable_set, /* Enable set */ 328 phy_null_enable_get, /* Enable get */ 329 phy_null_set, /* Duplex set */ 330 phy_null_one_get, /* Duplex get */ 331 phy_xehg_speed_set, /* Speed set */ 332 phy_xehg_speed_get, /* Speed get */ 333 phy_null_set, /* Master set */ 334 phy_null_zero_get, /* Master get */ 335 phy_null_set, /* ANA set */ 336 phy_null_an_get, /* ANA get */ 337 phy_null_mode_set, /* Local Advert set */ 338 phy_null_mode_get, /* Local Advert get */ 339 phy_null_mode_get, /* Remote Advert get */ 340 phy_8703_lb_set, /* PHY loopback set */ 341 phy_8703_lb_get, /* PHY loopback set */ 342 phy_null_interface_set, /* IO Interface set */ 343 phy_xehg_interface_get, /* IO Interface get */ 344 phy_xehg_ability_get, /* PHY abilities mask */ 345 NULL, 346 NULL, 347 phy_null_mdix_set, 348 phy_null_mdix_get, 349 phy_null_mdix_status_get, 350 NULL, 351 NULL, 352 phy_null_medium_get, 353 NULL, /* phy_cable_diag */ 354 NULL, /* phy_link_change */ 355 NULL, /* phy_control_set */ 356 NULL, /* phy_control_get */ 357 NULL, /* phy_reg_read */ 358 NULL, /* phy_reg_write */ 359 NULL, /* phy_reg_modify */ 360 NULL, /* phy_notify */ 361 }; 362 363 #else /* INCLUDE_PHY_8703 */ 364 int _soc_phy_8703_not_empty; 365 #endif /* INCLUDE_PHY_8703 */ 366