1/***********************license start*************** 2 * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights 3 * reserved. 4 * 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * * Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following 15 * disclaimer in the documentation and/or other materials provided 16 * with the distribution. 17 * 18 * * Neither the name of Cavium Networks nor the names of 19 * its contributors may be used to endorse or promote products 20 * derived from this software without specific prior written 21 * permission. 22 * 23 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 24 * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS 25 * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH 26 * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY 27 * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT 28 * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES 29 * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR 30 * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET 31 * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT 32 * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 33 * 34 * 35 * For any questions regarding licensing please contact marketing@caviumnetworks.com 36 * 37 ***********************license end**************************************/ 38 39 40 41 42 43 44/** 45 * @file 46 * 47 * Helper functions to abstract board specific data about 48 * network ports from the rest of the cvmx-helper files. 49 * 50 * <hr>$Revision: 41946 $<hr> 51 */ 52#include "cvmx.h" 53#include "cvmx-app-init.h" 54#include "cvmx-mdio.h" 55#include "cvmx-sysinfo.h" 56#include "cvmx-helper.h" 57#include "cvmx-helper-util.h" 58#include "cvmx-helper-board.h" 59 60/** 61 * cvmx_override_board_link_get(int ipd_port) is a function 62 * pointer. It is meant to allow customization of the process of 63 * talking to a PHY to determine link speed. It is called every 64 * time a PHY must be polled for link status. Users should set 65 * this pointer to a function before calling any cvmx-helper 66 * operations. 67 */ 68CVMX_SHARED cvmx_helper_link_info_t (*cvmx_override_board_link_get)(int ipd_port) = NULL; 69 70/** 71 * Return the MII PHY address associated with the given IPD 72 * port. A result of -1 means there isn't a MII capable PHY 73 * connected to this port. On chips supporting multiple MII 74 * busses the bus number is encoded in bits <15:8>. 75 * 76 * This function must be modified for every new Octeon board. 77 * Internally it uses switch statements based on the cvmx_sysinfo 78 * data to determine board types and revisions. It replies on the 79 * fact that every Octeon board receives a unique board type 80 * enumeration from the bootloader. 81 * 82 * @param ipd_port Octeon IPD port to get the MII address for. 83 * 84 * @return MII PHY address and bus number or -1. 85 */ 86int cvmx_helper_board_get_mii_address(int ipd_port) 87{ 88 /* 89 * Board types we have to know at compile-time. 90 */ 91#ifdef OCTEON_BOARD_CAPK_0100ND 92 switch (ipd_port) { 93 case 0: 94 return 2; 95 case 1: 96 return 3; 97 case 2: 98 /* XXX Switch PHY? */ 99 return -1; 100 default: 101 return -1; 102 } 103#endif 104 105 /* 106 * For board types we can determine at runtime. 107 */ 108 switch (cvmx_sysinfo_get()->board_type) 109 { 110 case CVMX_BOARD_TYPE_SIM: 111 /* Simulator doesn't have MII */ 112 return -1; 113 case CVMX_BOARD_TYPE_EBT3000: 114 case CVMX_BOARD_TYPE_EBT5800: 115 case CVMX_BOARD_TYPE_THUNDER: 116 case CVMX_BOARD_TYPE_NICPRO2: 117#if defined(OCTEON_VENDOR_LANNER) 118 case CVMX_BOARD_TYPE_CUST_LANNER_MR955: 119#endif 120 /* Interface 0 is SPI4, interface 1 is RGMII */ 121 if ((ipd_port >= 16) && (ipd_port < 20)) 122 return ipd_port - 16; 123 else 124 return -1; 125 case CVMX_BOARD_TYPE_KODAMA: 126 case CVMX_BOARD_TYPE_EBH3100: 127 case CVMX_BOARD_TYPE_HIKARI: 128 case CVMX_BOARD_TYPE_CN3010_EVB_HS5: 129 case CVMX_BOARD_TYPE_CN3005_EVB_HS5: 130 case CVMX_BOARD_TYPE_CN3020_EVB_HS5: 131 /* Port 0 is WAN connected to a PHY, Port 1 is GMII connected to a 132 switch */ 133 if (ipd_port == 0) 134 return 4; 135 else if (ipd_port == 1) 136 return 9; 137 else 138 return -1; 139 case CVMX_BOARD_TYPE_NAC38: 140 /* Board has 8 RGMII ports PHYs are 0-7 */ 141 if ((ipd_port >= 0) && (ipd_port < 4)) 142 return ipd_port; 143 else if ((ipd_port >= 16) && (ipd_port < 20)) 144 return ipd_port - 16 + 4; 145 else 146 return -1; 147 case CVMX_BOARD_TYPE_EBH3000: 148 /* Board has dual SPI4 and no PHYs */ 149 return -1; 150 case CVMX_BOARD_TYPE_EBH5200: 151 case CVMX_BOARD_TYPE_EBH5201: 152 case CVMX_BOARD_TYPE_EBT5200: 153 /* Board has 4 SGMII ports. The PHYs start right after the MII 154 ports MII0 = 0, MII1 = 1, SGMII = 2-5 */ 155 if ((ipd_port >= 0) && (ipd_port < 4)) 156 return ipd_port+2; 157 else 158 return -1; 159 case CVMX_BOARD_TYPE_EBH5600: 160 case CVMX_BOARD_TYPE_EBH5601: 161 /* Board has 8 SGMII ports. 4 connect out, two connect to a switch, 162 and 2 loop to each other */ 163 if ((ipd_port >= 0) && (ipd_port < 4)) 164 return ipd_port+1; 165 else 166 return -1; 167 case CVMX_BOARD_TYPE_CUST_NB5: 168 if (ipd_port == 2) 169 return 4; 170 else 171 return -1; 172 case CVMX_BOARD_TYPE_NIC_XLE_4G: 173 /* Board has 4 SGMII ports. connected QLM3(interface 1) */ 174 if ((ipd_port >= 16) && (ipd_port < 20)) 175 return ipd_port - 16 + 1; 176 else 177 return -1; 178 case CVMX_BOARD_TYPE_BBGW_REF: 179 return -1; /* No PHYs are connected to Octeon, everything is through switch */ 180 181 /* Private vendor-defined boards. */ 182#if defined(OCTEON_VENDOR_LANNER) 183 case CVMX_BOARD_TYPE_CUST_LANNER_MR320:
| 1/***********************license start*************** 2 * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights 3 * reserved. 4 * 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * * Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following 15 * disclaimer in the documentation and/or other materials provided 16 * with the distribution. 17 * 18 * * Neither the name of Cavium Networks nor the names of 19 * its contributors may be used to endorse or promote products 20 * derived from this software without specific prior written 21 * permission. 22 * 23 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 24 * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS 25 * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH 26 * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY 27 * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT 28 * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES 29 * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR 30 * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET 31 * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT 32 * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 33 * 34 * 35 * For any questions regarding licensing please contact marketing@caviumnetworks.com 36 * 37 ***********************license end**************************************/ 38 39 40 41 42 43 44/** 45 * @file 46 * 47 * Helper functions to abstract board specific data about 48 * network ports from the rest of the cvmx-helper files. 49 * 50 * <hr>$Revision: 41946 $<hr> 51 */ 52#include "cvmx.h" 53#include "cvmx-app-init.h" 54#include "cvmx-mdio.h" 55#include "cvmx-sysinfo.h" 56#include "cvmx-helper.h" 57#include "cvmx-helper-util.h" 58#include "cvmx-helper-board.h" 59 60/** 61 * cvmx_override_board_link_get(int ipd_port) is a function 62 * pointer. It is meant to allow customization of the process of 63 * talking to a PHY to determine link speed. It is called every 64 * time a PHY must be polled for link status. Users should set 65 * this pointer to a function before calling any cvmx-helper 66 * operations. 67 */ 68CVMX_SHARED cvmx_helper_link_info_t (*cvmx_override_board_link_get)(int ipd_port) = NULL; 69 70/** 71 * Return the MII PHY address associated with the given IPD 72 * port. A result of -1 means there isn't a MII capable PHY 73 * connected to this port. On chips supporting multiple MII 74 * busses the bus number is encoded in bits <15:8>. 75 * 76 * This function must be modified for every new Octeon board. 77 * Internally it uses switch statements based on the cvmx_sysinfo 78 * data to determine board types and revisions. It replies on the 79 * fact that every Octeon board receives a unique board type 80 * enumeration from the bootloader. 81 * 82 * @param ipd_port Octeon IPD port to get the MII address for. 83 * 84 * @return MII PHY address and bus number or -1. 85 */ 86int cvmx_helper_board_get_mii_address(int ipd_port) 87{ 88 /* 89 * Board types we have to know at compile-time. 90 */ 91#ifdef OCTEON_BOARD_CAPK_0100ND 92 switch (ipd_port) { 93 case 0: 94 return 2; 95 case 1: 96 return 3; 97 case 2: 98 /* XXX Switch PHY? */ 99 return -1; 100 default: 101 return -1; 102 } 103#endif 104 105 /* 106 * For board types we can determine at runtime. 107 */ 108 switch (cvmx_sysinfo_get()->board_type) 109 { 110 case CVMX_BOARD_TYPE_SIM: 111 /* Simulator doesn't have MII */ 112 return -1; 113 case CVMX_BOARD_TYPE_EBT3000: 114 case CVMX_BOARD_TYPE_EBT5800: 115 case CVMX_BOARD_TYPE_THUNDER: 116 case CVMX_BOARD_TYPE_NICPRO2: 117#if defined(OCTEON_VENDOR_LANNER) 118 case CVMX_BOARD_TYPE_CUST_LANNER_MR955: 119#endif 120 /* Interface 0 is SPI4, interface 1 is RGMII */ 121 if ((ipd_port >= 16) && (ipd_port < 20)) 122 return ipd_port - 16; 123 else 124 return -1; 125 case CVMX_BOARD_TYPE_KODAMA: 126 case CVMX_BOARD_TYPE_EBH3100: 127 case CVMX_BOARD_TYPE_HIKARI: 128 case CVMX_BOARD_TYPE_CN3010_EVB_HS5: 129 case CVMX_BOARD_TYPE_CN3005_EVB_HS5: 130 case CVMX_BOARD_TYPE_CN3020_EVB_HS5: 131 /* Port 0 is WAN connected to a PHY, Port 1 is GMII connected to a 132 switch */ 133 if (ipd_port == 0) 134 return 4; 135 else if (ipd_port == 1) 136 return 9; 137 else 138 return -1; 139 case CVMX_BOARD_TYPE_NAC38: 140 /* Board has 8 RGMII ports PHYs are 0-7 */ 141 if ((ipd_port >= 0) && (ipd_port < 4)) 142 return ipd_port; 143 else if ((ipd_port >= 16) && (ipd_port < 20)) 144 return ipd_port - 16 + 4; 145 else 146 return -1; 147 case CVMX_BOARD_TYPE_EBH3000: 148 /* Board has dual SPI4 and no PHYs */ 149 return -1; 150 case CVMX_BOARD_TYPE_EBH5200: 151 case CVMX_BOARD_TYPE_EBH5201: 152 case CVMX_BOARD_TYPE_EBT5200: 153 /* Board has 4 SGMII ports. The PHYs start right after the MII 154 ports MII0 = 0, MII1 = 1, SGMII = 2-5 */ 155 if ((ipd_port >= 0) && (ipd_port < 4)) 156 return ipd_port+2; 157 else 158 return -1; 159 case CVMX_BOARD_TYPE_EBH5600: 160 case CVMX_BOARD_TYPE_EBH5601: 161 /* Board has 8 SGMII ports. 4 connect out, two connect to a switch, 162 and 2 loop to each other */ 163 if ((ipd_port >= 0) && (ipd_port < 4)) 164 return ipd_port+1; 165 else 166 return -1; 167 case CVMX_BOARD_TYPE_CUST_NB5: 168 if (ipd_port == 2) 169 return 4; 170 else 171 return -1; 172 case CVMX_BOARD_TYPE_NIC_XLE_4G: 173 /* Board has 4 SGMII ports. connected QLM3(interface 1) */ 174 if ((ipd_port >= 16) && (ipd_port < 20)) 175 return ipd_port - 16 + 1; 176 else 177 return -1; 178 case CVMX_BOARD_TYPE_BBGW_REF: 179 return -1; /* No PHYs are connected to Octeon, everything is through switch */ 180 181 /* Private vendor-defined boards. */ 182#if defined(OCTEON_VENDOR_LANNER) 183 case CVMX_BOARD_TYPE_CUST_LANNER_MR320:
|
188 case 1: 189 return 1; 190 case 2: 191 return 2; 192 default: 193 return -1; 194 } 195#endif 196 } 197 198 /* Some unknown board. Somebody forgot to update this function... */ 199 cvmx_dprintf("cvmx_helper_board_get_mii_address: Unknown board type %d\n", 200 cvmx_sysinfo_get()->board_type); 201 return -1; 202} 203 204 205/** 206 * @INTERNAL 207 * This function is the board specific method of determining an 208 * ethernet ports link speed. Most Octeon boards have Marvell PHYs 209 * and are handled by the fall through case. This function must be 210 * updated for boards that don't have the normal Marvell PHYs. 211 * 212 * This function must be modified for every new Octeon board. 213 * Internally it uses switch statements based on the cvmx_sysinfo 214 * data to determine board types and revisions. It relies on the 215 * fact that every Octeon board receives a unique board type 216 * enumeration from the bootloader. 217 * 218 * @param ipd_port IPD input port associated with the port we want to get link 219 * status for. 220 * 221 * @return The ports link status. If the link isn't fully resolved, this must 222 * return zero. 223 */ 224cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port) 225{ 226 cvmx_helper_link_info_t result; 227 int phy_addr; 228 int is_broadcom_phy = 0; 229 230 /* Give the user a chance to override the processing of this function */ 231 if (cvmx_override_board_link_get) 232 return cvmx_override_board_link_get(ipd_port); 233 234 /* Unless we fix it later, all links are defaulted to down */ 235 result.u64 = 0; 236 237#if !defined(OCTEON_BOARD_CAPK_0100ND) 238 /* This switch statement should handle all ports that either don't use 239 Marvell PHYS, or don't support in-band status */ 240 switch (cvmx_sysinfo_get()->board_type) 241 { 242 case CVMX_BOARD_TYPE_SIM: 243 /* The simulator gives you a simulated 1Gbps full duplex link */ 244 result.s.link_up = 1; 245 result.s.full_duplex = 1; 246 result.s.speed = 1000; 247 return result; 248 case CVMX_BOARD_TYPE_EBH3100: 249 case CVMX_BOARD_TYPE_CN3010_EVB_HS5: 250 case CVMX_BOARD_TYPE_CN3005_EVB_HS5: 251 case CVMX_BOARD_TYPE_CN3020_EVB_HS5: 252 /* Port 1 on these boards is always Gigabit */ 253 if (ipd_port == 1) 254 { 255 result.s.link_up = 1; 256 result.s.full_duplex = 1; 257 result.s.speed = 1000; 258 return result; 259 } 260 /* Fall through to the generic code below */ 261 break; 262 case CVMX_BOARD_TYPE_CUST_NB5: 263 /* Port 1 on these boards is always Gigabit */ 264 if (ipd_port == 1) 265 { 266 result.s.link_up = 1; 267 result.s.full_duplex = 1; 268 result.s.speed = 1000; 269 return result; 270 } 271 else /* The other port uses a broadcom PHY */ 272 is_broadcom_phy = 1; 273 break; 274 case CVMX_BOARD_TYPE_BBGW_REF: 275 /* Port 1 on these boards is always Gigabit */ 276 if (ipd_port == 2) 277 { 278 /* Port 2 is not hooked up */ 279 result.u64 = 0; 280 return result; 281 } 282 else 283 { 284 /* Ports 0 and 1 connect to the switch */ 285 result.s.link_up = 1; 286 result.s.full_duplex = 1; 287 result.s.speed = 1000; 288 return result; 289 } 290 break; 291 /* Private vendor-defined boards. */ 292#if defined(OCTEON_VENDOR_LANNER) 293 case CVMX_BOARD_TYPE_CUST_LANNER_MR320: 294 /* Port 0 connects to the switch */ 295 if (ipd_port == 0) 296 { 297 result.s.link_up = 1; 298 result.s.full_duplex = 1; 299 result.s.speed = 1000; 300 return result; 301 } 302 break; 303#endif 304 } 305#endif 306 307 phy_addr = cvmx_helper_board_get_mii_address(ipd_port); 308 if (phy_addr != -1) 309 { 310 if (is_broadcom_phy) 311 { 312 /* Below we are going to read SMI/MDIO register 0x19 which works 313 on Broadcom parts */ 314 int phy_status = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 0x19); 315 switch ((phy_status>>8) & 0x7) 316 { 317 case 0: 318 result.u64 = 0; 319 break; 320 case 1: 321 result.s.link_up = 1; 322 result.s.full_duplex = 0; 323 result.s.speed = 10; 324 break; 325 case 2: 326 result.s.link_up = 1; 327 result.s.full_duplex = 1; 328 result.s.speed = 10; 329 break; 330 case 3: 331 result.s.link_up = 1; 332 result.s.full_duplex = 0; 333 result.s.speed = 100; 334 break; 335 case 4: 336 result.s.link_up = 1; 337 result.s.full_duplex = 1; 338 result.s.speed = 100; 339 break; 340 case 5: 341 result.s.link_up = 1; 342 result.s.full_duplex = 1; 343 result.s.speed = 100; 344 break; 345 case 6: 346 result.s.link_up = 1; 347 result.s.full_duplex = 0; 348 result.s.speed = 1000; 349 break; 350 case 7: 351 result.s.link_up = 1; 352 result.s.full_duplex = 1; 353 result.s.speed = 1000; 354 break; 355 } 356 } 357 else 358 { 359 /* This code assumes we are using a Marvell Gigabit PHY. All the 360 speed information can be read from register 17 in one go. Somebody 361 using a different PHY will need to handle it above in the board 362 specific area */ 363 int phy_status = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 17); 364 365 /* If the resolve bit 11 isn't set, see if autoneg is turned off 366 (bit 12, reg 0). The resolve bit doesn't get set properly when 367 autoneg is off, so force it */ 368 if ((phy_status & (1<<11)) == 0) 369 { 370 int auto_status = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 0); 371 if ((auto_status & (1<<12)) == 0) 372 phy_status |= 1<<11; 373 } 374 375 /* Only return a link if the PHY has finished auto negotiation 376 and set the resolved bit (bit 11) */ 377 if (phy_status & (1<<11)) 378 { 379#if defined(OCTEON_BOARD_CAPK_0100ND) 380 result.s.link_up = (phy_status>>10)&1; 381#else 382 result.s.link_up = 1; 383#endif 384 result.s.full_duplex = ((phy_status>>13)&1); 385 switch ((phy_status>>14)&3) 386 { 387 case 0: /* 10 Mbps */ 388 result.s.speed = 10; 389 break; 390 case 1: /* 100 Mbps */ 391 result.s.speed = 100; 392 break; 393 case 2: /* 1 Gbps */ 394 result.s.speed = 1000; 395 break; 396 case 3: /* Illegal */ 397 result.u64 = 0; 398 break; 399 } 400 } 401 } 402 } 403 else if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN58XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) 404 { 405 /* We don't have a PHY address, so attempt to use in-band status. It is 406 really important that boards not supporting in-band status never get 407 here. Reading broken in-band status tends to do bad things */ 408 cvmx_gmxx_rxx_rx_inbnd_t inband_status; 409 int interface = cvmx_helper_get_interface_num(ipd_port); 410 int index = cvmx_helper_get_interface_index_num(ipd_port); 411 inband_status.u64 = cvmx_read_csr(CVMX_GMXX_RXX_RX_INBND(index, interface)); 412 413 result.s.link_up = inband_status.s.status; 414 result.s.full_duplex = inband_status.s.duplex; 415 switch (inband_status.s.speed) 416 { 417 case 0: /* 10 Mbps */ 418 result.s.speed = 10; 419 break; 420 case 1: /* 100 Mbps */ 421 result.s.speed = 100; 422 break; 423 case 2: /* 1 Gbps */ 424 result.s.speed = 1000; 425 break; 426 case 3: /* Illegal */ 427 result.u64 = 0; 428 break; 429 } 430 } 431 else 432 { 433 /* We don't have a PHY address and we don't have in-band status. There 434 is no way to determine the link speed. Return down assuming this 435 port isn't wired */ 436 result.u64 = 0; 437 } 438 439 /* If link is down, return all fields as zero. */ 440 if (!result.s.link_up) 441 result.u64 = 0; 442 443 return result; 444} 445 446 447/** 448 * This function as a board specific method of changing the PHY 449 * speed, duplex, and auto-negotiation. This programs the PHY and 450 * not Octeon. This can be used to force Octeon's links to 451 * specific settings. 452 * 453 * @param phy_addr The address of the PHY to program 454 * @param enable_autoneg 455 * Non zero if you want to enable auto-negotiation. 456 * @param link_info Link speed to program. If the speed is zero and auto-negotiation 457 * is enabled, all possible negotiation speeds are advertised. 458 * 459 * @return Zero on success, negative on failure 460 */ 461int cvmx_helper_board_link_set_phy(int phy_addr, cvmx_helper_board_set_phy_link_flags_types_t link_flags, 462 cvmx_helper_link_info_t link_info) 463{ 464 465 /* Set the flow control settings based on link_flags */ 466 if ((link_flags & set_phy_link_flags_flow_control_mask) != set_phy_link_flags_flow_control_dont_touch) 467 { 468 cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; 469 reg_autoneg_adver.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER); 470 reg_autoneg_adver.s.asymmetric_pause = (link_flags & set_phy_link_flags_flow_control_mask) == set_phy_link_flags_flow_control_enable; 471 reg_autoneg_adver.s.pause = (link_flags & set_phy_link_flags_flow_control_mask) == set_phy_link_flags_flow_control_enable; 472 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER, reg_autoneg_adver.u16); 473 } 474 475 /* If speed isn't set and autoneg is on advertise all supported modes */ 476 if ((link_flags & set_phy_link_flags_autoneg) && (link_info.s.speed == 0)) 477 { 478 cvmx_mdio_phy_reg_control_t reg_control; 479 cvmx_mdio_phy_reg_status_t reg_status; 480 cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; 481 cvmx_mdio_phy_reg_extended_status_t reg_extended_status; 482 cvmx_mdio_phy_reg_control_1000_t reg_control_1000; 483 484 reg_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_STATUS); 485 reg_autoneg_adver.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER); 486 reg_autoneg_adver.s.advert_100base_t4 = reg_status.s.capable_100base_t4; 487 reg_autoneg_adver.s.advert_10base_tx_full = reg_status.s.capable_10_full; 488 reg_autoneg_adver.s.advert_10base_tx_half = reg_status.s.capable_10_half; 489 reg_autoneg_adver.s.advert_100base_tx_full = reg_status.s.capable_100base_x_full; 490 reg_autoneg_adver.s.advert_100base_tx_half = reg_status.s.capable_100base_x_half; 491 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER, reg_autoneg_adver.u16); 492 if (reg_status.s.capable_extended_status) 493 { 494 reg_extended_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_EXTENDED_STATUS); 495 reg_control_1000.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000); 496 reg_control_1000.s.advert_1000base_t_full = reg_extended_status.s.capable_1000base_t_full; 497 reg_control_1000.s.advert_1000base_t_half = reg_extended_status.s.capable_1000base_t_half; 498 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000, reg_control_1000.u16); 499 } 500 reg_control.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL); 501 reg_control.s.autoneg_enable = 1; 502 reg_control.s.restart_autoneg = 1; 503 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); 504 } 505 else if ((link_flags & set_phy_link_flags_autoneg)) 506 { 507 cvmx_mdio_phy_reg_control_t reg_control; 508 cvmx_mdio_phy_reg_status_t reg_status; 509 cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; 510 cvmx_mdio_phy_reg_extended_status_t reg_extended_status; 511 cvmx_mdio_phy_reg_control_1000_t reg_control_1000; 512 513 reg_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_STATUS); 514 reg_autoneg_adver.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER); 515 reg_autoneg_adver.s.advert_100base_t4 = 0; 516 reg_autoneg_adver.s.advert_10base_tx_full = 0; 517 reg_autoneg_adver.s.advert_10base_tx_half = 0; 518 reg_autoneg_adver.s.advert_100base_tx_full = 0; 519 reg_autoneg_adver.s.advert_100base_tx_half = 0; 520 if (reg_status.s.capable_extended_status) 521 { 522 reg_extended_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_EXTENDED_STATUS); 523 reg_control_1000.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000); 524 reg_control_1000.s.advert_1000base_t_full = 0; 525 reg_control_1000.s.advert_1000base_t_half = 0; 526 } 527 switch (link_info.s.speed) 528 { 529 case 10: 530 reg_autoneg_adver.s.advert_10base_tx_full = link_info.s.full_duplex; 531 reg_autoneg_adver.s.advert_10base_tx_half = !link_info.s.full_duplex; 532 break; 533 case 100: 534 reg_autoneg_adver.s.advert_100base_tx_full = link_info.s.full_duplex; 535 reg_autoneg_adver.s.advert_100base_tx_half = !link_info.s.full_duplex; 536 break; 537 case 1000: 538 reg_control_1000.s.advert_1000base_t_full = link_info.s.full_duplex; 539 reg_control_1000.s.advert_1000base_t_half = !link_info.s.full_duplex; 540 break; 541 } 542 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER, reg_autoneg_adver.u16); 543 if (reg_status.s.capable_extended_status) 544 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000, reg_control_1000.u16); 545 reg_control.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL); 546 reg_control.s.autoneg_enable = 1; 547 reg_control.s.restart_autoneg = 1; 548 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); 549 } 550 else 551 { 552 cvmx_mdio_phy_reg_control_t reg_control; 553 reg_control.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL); 554 reg_control.s.autoneg_enable = 0; 555 reg_control.s.restart_autoneg = 1; 556 reg_control.s.duplex = link_info.s.full_duplex; 557 if (link_info.s.speed == 1000) 558 { 559 reg_control.s.speed_msb = 1; 560 reg_control.s.speed_lsb = 0; 561 } 562 else if (link_info.s.speed == 100) 563 { 564 reg_control.s.speed_msb = 0; 565 reg_control.s.speed_lsb = 1; 566 } 567 else if (link_info.s.speed == 10) 568 { 569 reg_control.s.speed_msb = 0; 570 reg_control.s.speed_lsb = 0; 571 } 572 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); 573 } 574 return 0; 575} 576 577 578/** 579 * @INTERNAL 580 * This function is called by cvmx_helper_interface_probe() after it 581 * determines the number of ports Octeon can support on a specific 582 * interface. This function is the per board location to override 583 * this value. It is called with the number of ports Octeon might 584 * support and should return the number of actual ports on the 585 * board. 586 * 587 * This function must be modifed for every new Octeon board. 588 * Internally it uses switch statements based on the cvmx_sysinfo 589 * data to determine board types and revisions. It relys on the 590 * fact that every Octeon board receives a unique board type 591 * enumeration from the bootloader. 592 * 593 * @param interface Interface to probe 594 * @param supported_ports 595 * Number of ports Octeon supports. 596 * 597 * @return Number of ports the actual board supports. Many times this will 598 * simple be "support_ports". 599 */ 600int __cvmx_helper_board_interface_probe(int interface, int supported_ports) 601{ 602 switch (cvmx_sysinfo_get()->board_type) 603 { 604 case CVMX_BOARD_TYPE_CN3005_EVB_HS5: 605 if (interface == 0) 606 return 2; 607 break; 608 case CVMX_BOARD_TYPE_BBGW_REF: 609 if (interface == 0) 610 return 2; 611 break; 612 case CVMX_BOARD_TYPE_NIC_XLE_4G: 613 if (interface == 0) 614 return 0; 615 break; 616 /* The 2nd interface on the EBH5600 is connected to the Marvel switch, 617 which we don't support. Disable ports connected to it */ 618 case CVMX_BOARD_TYPE_EBH5600: 619 if (interface == 1) 620 return 0; 621 break; 622#if defined(OCTEON_VENDOR_LANNER) 623 case CVMX_BOARD_TYPE_CUST_LANNER_MR955: 624 if (interface == 1) 625 return 12; 626 break; 627#endif 628 } 629#ifdef CVMX_BUILD_FOR_UBOOT 630 if (CVMX_HELPER_INTERFACE_MODE_SPI == cvmx_helper_interface_get_mode(interface) && getenv("disable_spi")) 631 return 0; 632#endif 633 return supported_ports; 634} 635 636 637/** 638 * @INTERNAL 639 * Enable packet input/output from the hardware. This function is 640 * called after by cvmx_helper_packet_hardware_enable() to 641 * perform board specific initialization. For most boards 642 * nothing is needed. 643 * 644 * @param interface Interface to enable 645 * 646 * @return Zero on success, negative on failure 647 */ 648int __cvmx_helper_board_hardware_enable(int interface) 649{ 650 if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5) 651 { 652 if (interface == 0) 653 { 654 /* Different config for switch port */ 655 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(1, interface), 0); 656 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(1, interface), 0); 657 /* Boards with gigabit WAN ports need a different setting that is 658 compatible with 100 Mbit settings */ 659 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 0xc); 660 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 0xc); 661 } 662 } 663 else if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3010_EVB_HS5) 664 { 665 /* Broadcom PHYs require differnet ASX clocks. Unfortunately 666 many customer don't define a new board Id and simply 667 mangle the CN3010_EVB_HS5 */ 668 if (interface == 0) 669 { 670 /* Some customers boards use a hacked up bootloader that identifies them as 671 ** CN3010_EVB_HS5 evaluation boards. This leads to all kinds of configuration 672 ** problems. Detect one case, and print warning, while trying to do the right thing. 673 */ 674 int phy_addr = cvmx_helper_board_get_mii_address(0); 675 if (phy_addr != -1) 676 { 677 int phy_identifier = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 0x2); 678 /* Is it a Broadcom PHY? */ 679 if (phy_identifier == 0x0143) 680 { 681 cvmx_dprintf("\n"); 682 cvmx_dprintf("ERROR:\n"); 683 cvmx_dprintf("ERROR: Board type is CVMX_BOARD_TYPE_CN3010_EVB_HS5, but Broadcom PHY found.\n"); 684 cvmx_dprintf("ERROR: The board type is mis-configured, and software malfunctions are likely.\n"); 685 cvmx_dprintf("ERROR: All boards require a unique board type to identify them.\n"); 686 cvmx_dprintf("ERROR:\n"); 687 cvmx_dprintf("\n"); 688 cvmx_wait(1000000000); 689 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 5); 690 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 5); 691 } 692 } 693 } 694 } 695 return 0; 696} 697 698cvmx_helper_board_usb_clock_types_t __cvmx_helper_board_usb_get_clock_type(void) 699{ 700 switch (cvmx_sysinfo_get()->board_type) { 701 case CVMX_BOARD_TYPE_BBGW_REF: 702#if defined(OCTEON_VENDOR_LANNER) 703 case CVMX_BOARD_TYPE_CUST_LANNER_MR320: 704#endif 705 return USB_CLOCK_TYPE_CRYSTAL_12; 706 } 707 return USB_CLOCK_TYPE_REF_48; 708} 709 710int __cvmx_helper_board_usb_get_num_ports(int supported_ports) 711{ 712 switch (cvmx_sysinfo_get()->board_type) { 713 case CVMX_BOARD_TYPE_NIC_XLE_4G: 714 return 0; 715 } 716 717 return supported_ports; 718} 719 720
| 189 case 1: 190 return 1; 191 case 2: 192 return 2; 193 default: 194 return -1; 195 } 196#endif 197 } 198 199 /* Some unknown board. Somebody forgot to update this function... */ 200 cvmx_dprintf("cvmx_helper_board_get_mii_address: Unknown board type %d\n", 201 cvmx_sysinfo_get()->board_type); 202 return -1; 203} 204 205 206/** 207 * @INTERNAL 208 * This function is the board specific method of determining an 209 * ethernet ports link speed. Most Octeon boards have Marvell PHYs 210 * and are handled by the fall through case. This function must be 211 * updated for boards that don't have the normal Marvell PHYs. 212 * 213 * This function must be modified for every new Octeon board. 214 * Internally it uses switch statements based on the cvmx_sysinfo 215 * data to determine board types and revisions. It relies on the 216 * fact that every Octeon board receives a unique board type 217 * enumeration from the bootloader. 218 * 219 * @param ipd_port IPD input port associated with the port we want to get link 220 * status for. 221 * 222 * @return The ports link status. If the link isn't fully resolved, this must 223 * return zero. 224 */ 225cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port) 226{ 227 cvmx_helper_link_info_t result; 228 int phy_addr; 229 int is_broadcom_phy = 0; 230 231 /* Give the user a chance to override the processing of this function */ 232 if (cvmx_override_board_link_get) 233 return cvmx_override_board_link_get(ipd_port); 234 235 /* Unless we fix it later, all links are defaulted to down */ 236 result.u64 = 0; 237 238#if !defined(OCTEON_BOARD_CAPK_0100ND) 239 /* This switch statement should handle all ports that either don't use 240 Marvell PHYS, or don't support in-band status */ 241 switch (cvmx_sysinfo_get()->board_type) 242 { 243 case CVMX_BOARD_TYPE_SIM: 244 /* The simulator gives you a simulated 1Gbps full duplex link */ 245 result.s.link_up = 1; 246 result.s.full_duplex = 1; 247 result.s.speed = 1000; 248 return result; 249 case CVMX_BOARD_TYPE_EBH3100: 250 case CVMX_BOARD_TYPE_CN3010_EVB_HS5: 251 case CVMX_BOARD_TYPE_CN3005_EVB_HS5: 252 case CVMX_BOARD_TYPE_CN3020_EVB_HS5: 253 /* Port 1 on these boards is always Gigabit */ 254 if (ipd_port == 1) 255 { 256 result.s.link_up = 1; 257 result.s.full_duplex = 1; 258 result.s.speed = 1000; 259 return result; 260 } 261 /* Fall through to the generic code below */ 262 break; 263 case CVMX_BOARD_TYPE_CUST_NB5: 264 /* Port 1 on these boards is always Gigabit */ 265 if (ipd_port == 1) 266 { 267 result.s.link_up = 1; 268 result.s.full_duplex = 1; 269 result.s.speed = 1000; 270 return result; 271 } 272 else /* The other port uses a broadcom PHY */ 273 is_broadcom_phy = 1; 274 break; 275 case CVMX_BOARD_TYPE_BBGW_REF: 276 /* Port 1 on these boards is always Gigabit */ 277 if (ipd_port == 2) 278 { 279 /* Port 2 is not hooked up */ 280 result.u64 = 0; 281 return result; 282 } 283 else 284 { 285 /* Ports 0 and 1 connect to the switch */ 286 result.s.link_up = 1; 287 result.s.full_duplex = 1; 288 result.s.speed = 1000; 289 return result; 290 } 291 break; 292 /* Private vendor-defined boards. */ 293#if defined(OCTEON_VENDOR_LANNER) 294 case CVMX_BOARD_TYPE_CUST_LANNER_MR320: 295 /* Port 0 connects to the switch */ 296 if (ipd_port == 0) 297 { 298 result.s.link_up = 1; 299 result.s.full_duplex = 1; 300 result.s.speed = 1000; 301 return result; 302 } 303 break; 304#endif 305 } 306#endif 307 308 phy_addr = cvmx_helper_board_get_mii_address(ipd_port); 309 if (phy_addr != -1) 310 { 311 if (is_broadcom_phy) 312 { 313 /* Below we are going to read SMI/MDIO register 0x19 which works 314 on Broadcom parts */ 315 int phy_status = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 0x19); 316 switch ((phy_status>>8) & 0x7) 317 { 318 case 0: 319 result.u64 = 0; 320 break; 321 case 1: 322 result.s.link_up = 1; 323 result.s.full_duplex = 0; 324 result.s.speed = 10; 325 break; 326 case 2: 327 result.s.link_up = 1; 328 result.s.full_duplex = 1; 329 result.s.speed = 10; 330 break; 331 case 3: 332 result.s.link_up = 1; 333 result.s.full_duplex = 0; 334 result.s.speed = 100; 335 break; 336 case 4: 337 result.s.link_up = 1; 338 result.s.full_duplex = 1; 339 result.s.speed = 100; 340 break; 341 case 5: 342 result.s.link_up = 1; 343 result.s.full_duplex = 1; 344 result.s.speed = 100; 345 break; 346 case 6: 347 result.s.link_up = 1; 348 result.s.full_duplex = 0; 349 result.s.speed = 1000; 350 break; 351 case 7: 352 result.s.link_up = 1; 353 result.s.full_duplex = 1; 354 result.s.speed = 1000; 355 break; 356 } 357 } 358 else 359 { 360 /* This code assumes we are using a Marvell Gigabit PHY. All the 361 speed information can be read from register 17 in one go. Somebody 362 using a different PHY will need to handle it above in the board 363 specific area */ 364 int phy_status = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 17); 365 366 /* If the resolve bit 11 isn't set, see if autoneg is turned off 367 (bit 12, reg 0). The resolve bit doesn't get set properly when 368 autoneg is off, so force it */ 369 if ((phy_status & (1<<11)) == 0) 370 { 371 int auto_status = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 0); 372 if ((auto_status & (1<<12)) == 0) 373 phy_status |= 1<<11; 374 } 375 376 /* Only return a link if the PHY has finished auto negotiation 377 and set the resolved bit (bit 11) */ 378 if (phy_status & (1<<11)) 379 { 380#if defined(OCTEON_BOARD_CAPK_0100ND) 381 result.s.link_up = (phy_status>>10)&1; 382#else 383 result.s.link_up = 1; 384#endif 385 result.s.full_duplex = ((phy_status>>13)&1); 386 switch ((phy_status>>14)&3) 387 { 388 case 0: /* 10 Mbps */ 389 result.s.speed = 10; 390 break; 391 case 1: /* 100 Mbps */ 392 result.s.speed = 100; 393 break; 394 case 2: /* 1 Gbps */ 395 result.s.speed = 1000; 396 break; 397 case 3: /* Illegal */ 398 result.u64 = 0; 399 break; 400 } 401 } 402 } 403 } 404 else if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN58XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) 405 { 406 /* We don't have a PHY address, so attempt to use in-band status. It is 407 really important that boards not supporting in-band status never get 408 here. Reading broken in-band status tends to do bad things */ 409 cvmx_gmxx_rxx_rx_inbnd_t inband_status; 410 int interface = cvmx_helper_get_interface_num(ipd_port); 411 int index = cvmx_helper_get_interface_index_num(ipd_port); 412 inband_status.u64 = cvmx_read_csr(CVMX_GMXX_RXX_RX_INBND(index, interface)); 413 414 result.s.link_up = inband_status.s.status; 415 result.s.full_duplex = inband_status.s.duplex; 416 switch (inband_status.s.speed) 417 { 418 case 0: /* 10 Mbps */ 419 result.s.speed = 10; 420 break; 421 case 1: /* 100 Mbps */ 422 result.s.speed = 100; 423 break; 424 case 2: /* 1 Gbps */ 425 result.s.speed = 1000; 426 break; 427 case 3: /* Illegal */ 428 result.u64 = 0; 429 break; 430 } 431 } 432 else 433 { 434 /* We don't have a PHY address and we don't have in-band status. There 435 is no way to determine the link speed. Return down assuming this 436 port isn't wired */ 437 result.u64 = 0; 438 } 439 440 /* If link is down, return all fields as zero. */ 441 if (!result.s.link_up) 442 result.u64 = 0; 443 444 return result; 445} 446 447 448/** 449 * This function as a board specific method of changing the PHY 450 * speed, duplex, and auto-negotiation. This programs the PHY and 451 * not Octeon. This can be used to force Octeon's links to 452 * specific settings. 453 * 454 * @param phy_addr The address of the PHY to program 455 * @param enable_autoneg 456 * Non zero if you want to enable auto-negotiation. 457 * @param link_info Link speed to program. If the speed is zero and auto-negotiation 458 * is enabled, all possible negotiation speeds are advertised. 459 * 460 * @return Zero on success, negative on failure 461 */ 462int cvmx_helper_board_link_set_phy(int phy_addr, cvmx_helper_board_set_phy_link_flags_types_t link_flags, 463 cvmx_helper_link_info_t link_info) 464{ 465 466 /* Set the flow control settings based on link_flags */ 467 if ((link_flags & set_phy_link_flags_flow_control_mask) != set_phy_link_flags_flow_control_dont_touch) 468 { 469 cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; 470 reg_autoneg_adver.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER); 471 reg_autoneg_adver.s.asymmetric_pause = (link_flags & set_phy_link_flags_flow_control_mask) == set_phy_link_flags_flow_control_enable; 472 reg_autoneg_adver.s.pause = (link_flags & set_phy_link_flags_flow_control_mask) == set_phy_link_flags_flow_control_enable; 473 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER, reg_autoneg_adver.u16); 474 } 475 476 /* If speed isn't set and autoneg is on advertise all supported modes */ 477 if ((link_flags & set_phy_link_flags_autoneg) && (link_info.s.speed == 0)) 478 { 479 cvmx_mdio_phy_reg_control_t reg_control; 480 cvmx_mdio_phy_reg_status_t reg_status; 481 cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; 482 cvmx_mdio_phy_reg_extended_status_t reg_extended_status; 483 cvmx_mdio_phy_reg_control_1000_t reg_control_1000; 484 485 reg_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_STATUS); 486 reg_autoneg_adver.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER); 487 reg_autoneg_adver.s.advert_100base_t4 = reg_status.s.capable_100base_t4; 488 reg_autoneg_adver.s.advert_10base_tx_full = reg_status.s.capable_10_full; 489 reg_autoneg_adver.s.advert_10base_tx_half = reg_status.s.capable_10_half; 490 reg_autoneg_adver.s.advert_100base_tx_full = reg_status.s.capable_100base_x_full; 491 reg_autoneg_adver.s.advert_100base_tx_half = reg_status.s.capable_100base_x_half; 492 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER, reg_autoneg_adver.u16); 493 if (reg_status.s.capable_extended_status) 494 { 495 reg_extended_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_EXTENDED_STATUS); 496 reg_control_1000.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000); 497 reg_control_1000.s.advert_1000base_t_full = reg_extended_status.s.capable_1000base_t_full; 498 reg_control_1000.s.advert_1000base_t_half = reg_extended_status.s.capable_1000base_t_half; 499 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000, reg_control_1000.u16); 500 } 501 reg_control.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL); 502 reg_control.s.autoneg_enable = 1; 503 reg_control.s.restart_autoneg = 1; 504 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); 505 } 506 else if ((link_flags & set_phy_link_flags_autoneg)) 507 { 508 cvmx_mdio_phy_reg_control_t reg_control; 509 cvmx_mdio_phy_reg_status_t reg_status; 510 cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; 511 cvmx_mdio_phy_reg_extended_status_t reg_extended_status; 512 cvmx_mdio_phy_reg_control_1000_t reg_control_1000; 513 514 reg_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_STATUS); 515 reg_autoneg_adver.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER); 516 reg_autoneg_adver.s.advert_100base_t4 = 0; 517 reg_autoneg_adver.s.advert_10base_tx_full = 0; 518 reg_autoneg_adver.s.advert_10base_tx_half = 0; 519 reg_autoneg_adver.s.advert_100base_tx_full = 0; 520 reg_autoneg_adver.s.advert_100base_tx_half = 0; 521 if (reg_status.s.capable_extended_status) 522 { 523 reg_extended_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_EXTENDED_STATUS); 524 reg_control_1000.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000); 525 reg_control_1000.s.advert_1000base_t_full = 0; 526 reg_control_1000.s.advert_1000base_t_half = 0; 527 } 528 switch (link_info.s.speed) 529 { 530 case 10: 531 reg_autoneg_adver.s.advert_10base_tx_full = link_info.s.full_duplex; 532 reg_autoneg_adver.s.advert_10base_tx_half = !link_info.s.full_duplex; 533 break; 534 case 100: 535 reg_autoneg_adver.s.advert_100base_tx_full = link_info.s.full_duplex; 536 reg_autoneg_adver.s.advert_100base_tx_half = !link_info.s.full_duplex; 537 break; 538 case 1000: 539 reg_control_1000.s.advert_1000base_t_full = link_info.s.full_duplex; 540 reg_control_1000.s.advert_1000base_t_half = !link_info.s.full_duplex; 541 break; 542 } 543 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER, reg_autoneg_adver.u16); 544 if (reg_status.s.capable_extended_status) 545 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000, reg_control_1000.u16); 546 reg_control.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL); 547 reg_control.s.autoneg_enable = 1; 548 reg_control.s.restart_autoneg = 1; 549 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); 550 } 551 else 552 { 553 cvmx_mdio_phy_reg_control_t reg_control; 554 reg_control.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL); 555 reg_control.s.autoneg_enable = 0; 556 reg_control.s.restart_autoneg = 1; 557 reg_control.s.duplex = link_info.s.full_duplex; 558 if (link_info.s.speed == 1000) 559 { 560 reg_control.s.speed_msb = 1; 561 reg_control.s.speed_lsb = 0; 562 } 563 else if (link_info.s.speed == 100) 564 { 565 reg_control.s.speed_msb = 0; 566 reg_control.s.speed_lsb = 1; 567 } 568 else if (link_info.s.speed == 10) 569 { 570 reg_control.s.speed_msb = 0; 571 reg_control.s.speed_lsb = 0; 572 } 573 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); 574 } 575 return 0; 576} 577 578 579/** 580 * @INTERNAL 581 * This function is called by cvmx_helper_interface_probe() after it 582 * determines the number of ports Octeon can support on a specific 583 * interface. This function is the per board location to override 584 * this value. It is called with the number of ports Octeon might 585 * support and should return the number of actual ports on the 586 * board. 587 * 588 * This function must be modifed for every new Octeon board. 589 * Internally it uses switch statements based on the cvmx_sysinfo 590 * data to determine board types and revisions. It relys on the 591 * fact that every Octeon board receives a unique board type 592 * enumeration from the bootloader. 593 * 594 * @param interface Interface to probe 595 * @param supported_ports 596 * Number of ports Octeon supports. 597 * 598 * @return Number of ports the actual board supports. Many times this will 599 * simple be "support_ports". 600 */ 601int __cvmx_helper_board_interface_probe(int interface, int supported_ports) 602{ 603 switch (cvmx_sysinfo_get()->board_type) 604 { 605 case CVMX_BOARD_TYPE_CN3005_EVB_HS5: 606 if (interface == 0) 607 return 2; 608 break; 609 case CVMX_BOARD_TYPE_BBGW_REF: 610 if (interface == 0) 611 return 2; 612 break; 613 case CVMX_BOARD_TYPE_NIC_XLE_4G: 614 if (interface == 0) 615 return 0; 616 break; 617 /* The 2nd interface on the EBH5600 is connected to the Marvel switch, 618 which we don't support. Disable ports connected to it */ 619 case CVMX_BOARD_TYPE_EBH5600: 620 if (interface == 1) 621 return 0; 622 break; 623#if defined(OCTEON_VENDOR_LANNER) 624 case CVMX_BOARD_TYPE_CUST_LANNER_MR955: 625 if (interface == 1) 626 return 12; 627 break; 628#endif 629 } 630#ifdef CVMX_BUILD_FOR_UBOOT 631 if (CVMX_HELPER_INTERFACE_MODE_SPI == cvmx_helper_interface_get_mode(interface) && getenv("disable_spi")) 632 return 0; 633#endif 634 return supported_ports; 635} 636 637 638/** 639 * @INTERNAL 640 * Enable packet input/output from the hardware. This function is 641 * called after by cvmx_helper_packet_hardware_enable() to 642 * perform board specific initialization. For most boards 643 * nothing is needed. 644 * 645 * @param interface Interface to enable 646 * 647 * @return Zero on success, negative on failure 648 */ 649int __cvmx_helper_board_hardware_enable(int interface) 650{ 651 if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5) 652 { 653 if (interface == 0) 654 { 655 /* Different config for switch port */ 656 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(1, interface), 0); 657 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(1, interface), 0); 658 /* Boards with gigabit WAN ports need a different setting that is 659 compatible with 100 Mbit settings */ 660 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 0xc); 661 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 0xc); 662 } 663 } 664 else if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3010_EVB_HS5) 665 { 666 /* Broadcom PHYs require differnet ASX clocks. Unfortunately 667 many customer don't define a new board Id and simply 668 mangle the CN3010_EVB_HS5 */ 669 if (interface == 0) 670 { 671 /* Some customers boards use a hacked up bootloader that identifies them as 672 ** CN3010_EVB_HS5 evaluation boards. This leads to all kinds of configuration 673 ** problems. Detect one case, and print warning, while trying to do the right thing. 674 */ 675 int phy_addr = cvmx_helper_board_get_mii_address(0); 676 if (phy_addr != -1) 677 { 678 int phy_identifier = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 0x2); 679 /* Is it a Broadcom PHY? */ 680 if (phy_identifier == 0x0143) 681 { 682 cvmx_dprintf("\n"); 683 cvmx_dprintf("ERROR:\n"); 684 cvmx_dprintf("ERROR: Board type is CVMX_BOARD_TYPE_CN3010_EVB_HS5, but Broadcom PHY found.\n"); 685 cvmx_dprintf("ERROR: The board type is mis-configured, and software malfunctions are likely.\n"); 686 cvmx_dprintf("ERROR: All boards require a unique board type to identify them.\n"); 687 cvmx_dprintf("ERROR:\n"); 688 cvmx_dprintf("\n"); 689 cvmx_wait(1000000000); 690 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 5); 691 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 5); 692 } 693 } 694 } 695 } 696 return 0; 697} 698 699cvmx_helper_board_usb_clock_types_t __cvmx_helper_board_usb_get_clock_type(void) 700{ 701 switch (cvmx_sysinfo_get()->board_type) { 702 case CVMX_BOARD_TYPE_BBGW_REF: 703#if defined(OCTEON_VENDOR_LANNER) 704 case CVMX_BOARD_TYPE_CUST_LANNER_MR320: 705#endif 706 return USB_CLOCK_TYPE_CRYSTAL_12; 707 } 708 return USB_CLOCK_TYPE_REF_48; 709} 710 711int __cvmx_helper_board_usb_get_num_ports(int supported_ports) 712{ 713 switch (cvmx_sysinfo_get()->board_type) { 714 case CVMX_BOARD_TYPE_NIC_XLE_4G: 715 return 0; 716 } 717 718 return supported_ports; 719} 720 721
|