1210284Sjmallett/***********************license start*************** 2215990Sjmallett * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights 3215990Sjmallett * reserved. 4210284Sjmallett * 5210284Sjmallett * 6215990Sjmallett * Redistribution and use in source and binary forms, with or without 7215990Sjmallett * modification, are permitted provided that the following conditions are 8215990Sjmallett * met: 9210284Sjmallett * 10215990Sjmallett * * Redistributions of source code must retain the above copyright 11215990Sjmallett * notice, this list of conditions and the following disclaimer. 12210284Sjmallett * 13215990Sjmallett * * Redistributions in binary form must reproduce the above 14215990Sjmallett * copyright notice, this list of conditions and the following 15215990Sjmallett * disclaimer in the documentation and/or other materials provided 16215990Sjmallett * with the distribution. 17215990Sjmallett 18215990Sjmallett * * Neither the name of Cavium Networks nor the names of 19215990Sjmallett * its contributors may be used to endorse or promote products 20215990Sjmallett * derived from this software without specific prior written 21215990Sjmallett * permission. 22215990Sjmallett 23215990Sjmallett * This Software, including technical data, may be subject to U.S. export control 24215990Sjmallett * laws, including the U.S. Export Administration Act and its associated 25215990Sjmallett * regulations, and may be subject to export or import regulations in other 26215990Sjmallett * countries. 27215990Sjmallett 28215990Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29215990Sjmallett * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR 30215990Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31215990Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32215990Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33215990Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34215990Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35215990Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36215990Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37215990Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38210284Sjmallett ***********************license end**************************************/ 39210284Sjmallett 40210284Sjmallett 41210284Sjmallett 42210284Sjmallett 43210284Sjmallett 44210284Sjmallett 45215990Sjmallett 46210284Sjmallett/** 47210284Sjmallett * @file 48210284Sjmallett * 49210284Sjmallett * Helper functions to abstract board specific data about 50210284Sjmallett * network ports from the rest of the cvmx-helper files. 51210284Sjmallett * 52215990Sjmallett * <hr>$Revision: 49627 $<hr> 53210284Sjmallett */ 54215990Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 55215990Sjmallett#include <linux/module.h> 56215990Sjmallett#include <asm/octeon/cvmx.h> 57215990Sjmallett#include <asm/octeon/cvmx-bootinfo.h> 58215990Sjmallett#include <asm/octeon/cvmx-smix-defs.h> 59215990Sjmallett#include <asm/octeon/cvmx-gmxx-defs.h> 60215990Sjmallett#include <asm/octeon/cvmx-asxx-defs.h> 61215990Sjmallett#include <asm/octeon/cvmx-mdio.h> 62215990Sjmallett#include <asm/octeon/cvmx-helper.h> 63215990Sjmallett#include <asm/octeon/cvmx-helper-util.h> 64215990Sjmallett#include <asm/octeon/cvmx-helper-board.h> 65215990Sjmallett#include <asm/octeon/cvmx-twsi.h> 66215990Sjmallett#else 67210284Sjmallett#include "cvmx.h" 68210284Sjmallett#include "cvmx-app-init.h" 69215990Sjmallett#include "cvmx-sysinfo.h" 70215990Sjmallett#include "cvmx-twsi.h" 71210284Sjmallett#include "cvmx-mdio.h" 72210284Sjmallett#include "cvmx-helper.h" 73210284Sjmallett#include "cvmx-helper-util.h" 74210284Sjmallett#include "cvmx-helper-board.h" 75215990Sjmallett#endif 76210284Sjmallett 77210284Sjmallett/** 78210284Sjmallett * cvmx_override_board_link_get(int ipd_port) is a function 79210284Sjmallett * pointer. It is meant to allow customization of the process of 80210284Sjmallett * talking to a PHY to determine link speed. It is called every 81210284Sjmallett * time a PHY must be polled for link status. Users should set 82210284Sjmallett * this pointer to a function before calling any cvmx-helper 83210284Sjmallett * operations. 84210284Sjmallett */ 85210284SjmallettCVMX_SHARED cvmx_helper_link_info_t (*cvmx_override_board_link_get)(int ipd_port) = NULL; 86210284Sjmallett 87210284Sjmallett/** 88210284Sjmallett * Return the MII PHY address associated with the given IPD 89210284Sjmallett * port. A result of -1 means there isn't a MII capable PHY 90210284Sjmallett * connected to this port. On chips supporting multiple MII 91210284Sjmallett * busses the bus number is encoded in bits <15:8>. 92210284Sjmallett * 93210284Sjmallett * This function must be modified for every new Octeon board. 94210284Sjmallett * Internally it uses switch statements based on the cvmx_sysinfo 95210284Sjmallett * data to determine board types and revisions. It replies on the 96210284Sjmallett * fact that every Octeon board receives a unique board type 97210284Sjmallett * enumeration from the bootloader. 98210284Sjmallett * 99210284Sjmallett * @param ipd_port Octeon IPD port to get the MII address for. 100210284Sjmallett * 101210284Sjmallett * @return MII PHY address and bus number or -1. 102210284Sjmallett */ 103210284Sjmallettint cvmx_helper_board_get_mii_address(int ipd_port) 104210284Sjmallett{ 105210311Sjmallett /* 106210311Sjmallett * Board types we have to know at compile-time. 107210311Sjmallett */ 108210311Sjmallett#ifdef OCTEON_BOARD_CAPK_0100ND 109210311Sjmallett switch (ipd_port) { 110210311Sjmallett case 0: 111210311Sjmallett return 2; 112210311Sjmallett case 1: 113210311Sjmallett return 3; 114210311Sjmallett case 2: 115210311Sjmallett /* XXX Switch PHY? */ 116210311Sjmallett return -1; 117210311Sjmallett default: 118210311Sjmallett return -1; 119210311Sjmallett } 120210311Sjmallett#endif 121210311Sjmallett 122210311Sjmallett /* 123210311Sjmallett * For board types we can determine at runtime. 124210311Sjmallett */ 125210284Sjmallett switch (cvmx_sysinfo_get()->board_type) 126210284Sjmallett { 127210284Sjmallett case CVMX_BOARD_TYPE_SIM: 128210284Sjmallett /* Simulator doesn't have MII */ 129210284Sjmallett return -1; 130210284Sjmallett case CVMX_BOARD_TYPE_EBT3000: 131210284Sjmallett case CVMX_BOARD_TYPE_EBT5800: 132210284Sjmallett case CVMX_BOARD_TYPE_THUNDER: 133210284Sjmallett case CVMX_BOARD_TYPE_NICPRO2: 134210284Sjmallett /* Interface 0 is SPI4, interface 1 is RGMII */ 135210284Sjmallett if ((ipd_port >= 16) && (ipd_port < 20)) 136210284Sjmallett return ipd_port - 16; 137210284Sjmallett else 138210284Sjmallett return -1; 139215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_A: 140215990Sjmallett if (ipd_port == 0) 141215990Sjmallett return 0; 142215990Sjmallett else 143215990Sjmallett return -1; 144215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_U: 145215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_G: 146215990Sjmallett if (ipd_port == 0) 147215990Sjmallett return 0x1c; 148215990Sjmallett else 149215990Sjmallett return -1; 150210284Sjmallett case CVMX_BOARD_TYPE_KODAMA: 151210284Sjmallett case CVMX_BOARD_TYPE_EBH3100: 152210284Sjmallett case CVMX_BOARD_TYPE_HIKARI: 153210284Sjmallett case CVMX_BOARD_TYPE_CN3010_EVB_HS5: 154210284Sjmallett case CVMX_BOARD_TYPE_CN3005_EVB_HS5: 155210284Sjmallett case CVMX_BOARD_TYPE_CN3020_EVB_HS5: 156210284Sjmallett /* Port 0 is WAN connected to a PHY, Port 1 is GMII connected to a 157210284Sjmallett switch */ 158210284Sjmallett if (ipd_port == 0) 159210284Sjmallett return 4; 160210284Sjmallett else if (ipd_port == 1) 161210284Sjmallett return 9; 162210284Sjmallett else 163210284Sjmallett return -1; 164210284Sjmallett case CVMX_BOARD_TYPE_NAC38: 165210284Sjmallett /* Board has 8 RGMII ports PHYs are 0-7 */ 166210284Sjmallett if ((ipd_port >= 0) && (ipd_port < 4)) 167210284Sjmallett return ipd_port; 168210284Sjmallett else if ((ipd_port >= 16) && (ipd_port < 20)) 169210284Sjmallett return ipd_port - 16 + 4; 170210284Sjmallett else 171210284Sjmallett return -1; 172210284Sjmallett case CVMX_BOARD_TYPE_EBH3000: 173210284Sjmallett /* Board has dual SPI4 and no PHYs */ 174210284Sjmallett return -1; 175215990Sjmallett case CVMX_BOARD_TYPE_EBT5810: 176215990Sjmallett /* Board has 10g PHYs hooked up to the MII controller on the 177215990Sjmallett ** IXF18201 MAC. The 10G PHYS use clause 45 MDIO which the CN58XX 178215990Sjmallett ** does not support. All MII accesses go through the IXF part. */ 179215990Sjmallett return -1; 180210284Sjmallett case CVMX_BOARD_TYPE_EBH5200: 181210284Sjmallett case CVMX_BOARD_TYPE_EBH5201: 182210284Sjmallett case CVMX_BOARD_TYPE_EBT5200: 183215990Sjmallett /* Board has 2 management ports */ 184215990Sjmallett if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2))) 185215990Sjmallett return ipd_port - CVMX_HELPER_BOARD_MGMT_IPD_PORT; 186210284Sjmallett /* Board has 4 SGMII ports. The PHYs start right after the MII 187210284Sjmallett ports MII0 = 0, MII1 = 1, SGMII = 2-5 */ 188210284Sjmallett if ((ipd_port >= 0) && (ipd_port < 4)) 189210284Sjmallett return ipd_port+2; 190210284Sjmallett else 191210284Sjmallett return -1; 192210284Sjmallett case CVMX_BOARD_TYPE_EBH5600: 193210284Sjmallett case CVMX_BOARD_TYPE_EBH5601: 194215990Sjmallett case CVMX_BOARD_TYPE_EBH5610: 195215990Sjmallett /* Board has 1 management port */ 196215990Sjmallett if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT) 197215990Sjmallett return 0; 198210284Sjmallett /* Board has 8 SGMII ports. 4 connect out, two connect to a switch, 199210284Sjmallett and 2 loop to each other */ 200210284Sjmallett if ((ipd_port >= 0) && (ipd_port < 4)) 201210284Sjmallett return ipd_port+1; 202210284Sjmallett else 203210284Sjmallett return -1; 204215990Sjmallett case CVMX_BOARD_TYPE_EBB5600: 205215990Sjmallett { 206215990Sjmallett static unsigned char qlm_switch_addr = 0; 207215990Sjmallett 208215990Sjmallett /* Board has 1 management port */ 209215990Sjmallett if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT) 210215990Sjmallett return 0; 211215990Sjmallett 212215990Sjmallett /* Board has 8 SGMII ports. 4 connected QLM1, 4 connected QLM3 */ 213215990Sjmallett if ((ipd_port >= 0) && (ipd_port < 4)) 214215990Sjmallett { 215215990Sjmallett if (qlm_switch_addr != 0x3) 216215990Sjmallett { 217215990Sjmallett qlm_switch_addr = 0x3; /* QLM1 */ 218215990Sjmallett cvmx_twsix_write_ia(0, 0x71, 0, 1, 1, qlm_switch_addr); 219215990Sjmallett cvmx_wait_usec(11000); /* Let the write complete */ 220215990Sjmallett } 221215990Sjmallett return ipd_port+1 + (1<<8); 222215990Sjmallett } 223215990Sjmallett else if ((ipd_port >= 16) && (ipd_port < 20)) 224215990Sjmallett { 225215990Sjmallett if (qlm_switch_addr != 0xC) 226215990Sjmallett { 227215990Sjmallett qlm_switch_addr = 0xC; /* QLM3 */ 228215990Sjmallett cvmx_twsix_write_ia(0, 0x71, 0, 1, 1, qlm_switch_addr); 229215990Sjmallett cvmx_wait_usec(11000); /* Let the write complete */ 230215990Sjmallett } 231215990Sjmallett return ipd_port-16+1 + (1<<8); 232215990Sjmallett } 233215990Sjmallett else 234215990Sjmallett return -1; 235215990Sjmallett } 236215990Sjmallett case CVMX_BOARD_TYPE_EBB6300: 237215990Sjmallett /* Board has 2 management ports */ 238215990Sjmallett if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2))) 239215990Sjmallett return ipd_port - CVMX_HELPER_BOARD_MGMT_IPD_PORT + 4; 240215990Sjmallett if ((ipd_port >= 0) && (ipd_port < 4)) 241215990Sjmallett return ipd_port + 1 + (1<<8); 242215990Sjmallett else 243215990Sjmallett return -1; 244210284Sjmallett case CVMX_BOARD_TYPE_CUST_NB5: 245210284Sjmallett if (ipd_port == 2) 246210284Sjmallett return 4; 247210284Sjmallett else 248210284Sjmallett return -1; 249210284Sjmallett case CVMX_BOARD_TYPE_NIC_XLE_4G: 250210284Sjmallett /* Board has 4 SGMII ports. connected QLM3(interface 1) */ 251210284Sjmallett if ((ipd_port >= 16) && (ipd_port < 20)) 252210284Sjmallett return ipd_port - 16 + 1; 253210284Sjmallett else 254210284Sjmallett return -1; 255215990Sjmallett case CVMX_BOARD_TYPE_NIC_XLE_10G: 256215990Sjmallett return -1; /* We don't use clause 45 MDIO for anything */ 257210284Sjmallett case CVMX_BOARD_TYPE_BBGW_REF: 258210284Sjmallett return -1; /* No PHYs are connected to Octeon, everything is through switch */ 259215990Sjmallett case CVMX_BOARD_TYPE_CUST_WSX16: 260215990Sjmallett if (ipd_port >= 0 && ipd_port <= 3) 261215990Sjmallett return ipd_port; 262215990Sjmallett else if (ipd_port >= 16 && ipd_port <= 19) 263215990Sjmallett return ipd_port - 16 + 4; 264215990Sjmallett else 265215990Sjmallett return -1; 266210311Sjmallett 267210311Sjmallett /* Private vendor-defined boards. */ 268210311Sjmallett#if defined(OCTEON_VENDOR_LANNER) 269215014Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR955: 270215014Sjmallett /* Interface 1 is 12 BCM5482S PHYs. */ 271215014Sjmallett if ((ipd_port >= 16) && (ipd_port < 28)) 272215014Sjmallett return ipd_port - 16; 273215014Sjmallett return -1; 274215014Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR730: 275217214Sjmallett if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2))) 276217214Sjmallett return (ipd_port - CVMX_HELPER_BOARD_MGMT_IPD_PORT) + 0x81; 277215014Sjmallett if ((ipd_port >= 0) && (ipd_port < 4)) 278215014Sjmallett return ipd_port; 279215014Sjmallett return -1; 280210311Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR320: 281216476Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR321X: 282213346Sjmallett /* Port 0 is a Marvell 88E6161 switch, ports 1 and 2 are Marvell 283213346Sjmallett 88E1111 interfaces. */ 284210311Sjmallett switch (ipd_port) { 285210311Sjmallett case 0: 286213346Sjmallett return 16; 287210311Sjmallett case 1: 288210311Sjmallett return 1; 289210311Sjmallett case 2: 290210311Sjmallett return 2; 291210311Sjmallett default: 292210311Sjmallett return -1; 293210311Sjmallett } 294210311Sjmallett#endif 295210284Sjmallett } 296210284Sjmallett 297210284Sjmallett /* Some unknown board. Somebody forgot to update this function... */ 298215990Sjmallett cvmx_dprintf("%s: Unknown board type %d\n", 299215990Sjmallett __FUNCTION__, cvmx_sysinfo_get()->board_type); 300210284Sjmallett return -1; 301210284Sjmallett} 302215990Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 303215990SjmallettEXPORT_SYMBOL(cvmx_helper_board_get_mii_address); 304215990Sjmallett#endif 305210284Sjmallett 306210284Sjmallett 307210284Sjmallett/** 308210284Sjmallett * @INTERNAL 309210284Sjmallett * This function is the board specific method of determining an 310210284Sjmallett * ethernet ports link speed. Most Octeon boards have Marvell PHYs 311210284Sjmallett * and are handled by the fall through case. This function must be 312210284Sjmallett * updated for boards that don't have the normal Marvell PHYs. 313210284Sjmallett * 314210284Sjmallett * This function must be modified for every new Octeon board. 315210284Sjmallett * Internally it uses switch statements based on the cvmx_sysinfo 316210284Sjmallett * data to determine board types and revisions. It relies on the 317210284Sjmallett * fact that every Octeon board receives a unique board type 318210284Sjmallett * enumeration from the bootloader. 319210284Sjmallett * 320210284Sjmallett * @param ipd_port IPD input port associated with the port we want to get link 321210284Sjmallett * status for. 322210284Sjmallett * 323210284Sjmallett * @return The ports link status. If the link isn't fully resolved, this must 324210284Sjmallett * return zero. 325210284Sjmallett */ 326210284Sjmallettcvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port) 327210284Sjmallett{ 328210284Sjmallett cvmx_helper_link_info_t result; 329210284Sjmallett int phy_addr; 330210284Sjmallett int is_broadcom_phy = 0; 331210284Sjmallett 332210284Sjmallett /* Give the user a chance to override the processing of this function */ 333210284Sjmallett if (cvmx_override_board_link_get) 334210284Sjmallett return cvmx_override_board_link_get(ipd_port); 335210284Sjmallett 336210284Sjmallett /* Unless we fix it later, all links are defaulted to down */ 337210284Sjmallett result.u64 = 0; 338210284Sjmallett 339210311Sjmallett#if !defined(OCTEON_BOARD_CAPK_0100ND) 340210284Sjmallett /* This switch statement should handle all ports that either don't use 341210284Sjmallett Marvell PHYS, or don't support in-band status */ 342210284Sjmallett switch (cvmx_sysinfo_get()->board_type) 343210284Sjmallett { 344210284Sjmallett case CVMX_BOARD_TYPE_SIM: 345210284Sjmallett /* The simulator gives you a simulated 1Gbps full duplex link */ 346210284Sjmallett result.s.link_up = 1; 347210284Sjmallett result.s.full_duplex = 1; 348210284Sjmallett result.s.speed = 1000; 349210284Sjmallett return result; 350215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_A: 351215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_U: 352215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_G: 353215990Sjmallett break; 354210284Sjmallett case CVMX_BOARD_TYPE_EBH3100: 355210284Sjmallett case CVMX_BOARD_TYPE_CN3010_EVB_HS5: 356210284Sjmallett case CVMX_BOARD_TYPE_CN3005_EVB_HS5: 357210284Sjmallett case CVMX_BOARD_TYPE_CN3020_EVB_HS5: 358210284Sjmallett /* Port 1 on these boards is always Gigabit */ 359210284Sjmallett if (ipd_port == 1) 360210284Sjmallett { 361210284Sjmallett result.s.link_up = 1; 362210284Sjmallett result.s.full_duplex = 1; 363210284Sjmallett result.s.speed = 1000; 364210284Sjmallett return result; 365210284Sjmallett } 366210284Sjmallett /* Fall through to the generic code below */ 367210284Sjmallett break; 368215990Sjmallett case CVMX_BOARD_TYPE_EBH5600: 369215990Sjmallett case CVMX_BOARD_TYPE_EBH5601: 370215990Sjmallett case CVMX_BOARD_TYPE_EBH5610: 371215990Sjmallett /* Board has 1 management ports */ 372215990Sjmallett if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT) 373215990Sjmallett is_broadcom_phy = 1; 374215990Sjmallett break; 375215990Sjmallett case CVMX_BOARD_TYPE_EBH5200: 376215990Sjmallett case CVMX_BOARD_TYPE_EBH5201: 377215990Sjmallett case CVMX_BOARD_TYPE_EBT5200: 378215990Sjmallett /* Board has 2 management ports */ 379215990Sjmallett if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2))) 380215990Sjmallett is_broadcom_phy = 1; 381215990Sjmallett break; 382215990Sjmallett case CVMX_BOARD_TYPE_EBB6300: /* Only for MII mode, with PHY addresses 0/1. Default is RGMII*/ 383215990Sjmallett if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2)) 384215990Sjmallett && cvmx_helper_board_get_mii_address(ipd_port) >= 0 && cvmx_helper_board_get_mii_address(ipd_port) <= 1) 385215990Sjmallett is_broadcom_phy = 1; 386215990Sjmallett break; 387210284Sjmallett case CVMX_BOARD_TYPE_CUST_NB5: 388210284Sjmallett /* Port 1 on these boards is always Gigabit */ 389210284Sjmallett if (ipd_port == 1) 390210284Sjmallett { 391210284Sjmallett result.s.link_up = 1; 392210284Sjmallett result.s.full_duplex = 1; 393210284Sjmallett result.s.speed = 1000; 394210284Sjmallett return result; 395210284Sjmallett } 396210284Sjmallett else /* The other port uses a broadcom PHY */ 397210284Sjmallett is_broadcom_phy = 1; 398210284Sjmallett break; 399210284Sjmallett case CVMX_BOARD_TYPE_BBGW_REF: 400210284Sjmallett /* Port 1 on these boards is always Gigabit */ 401210284Sjmallett if (ipd_port == 2) 402215990Sjmallett { 403210284Sjmallett /* Port 2 is not hooked up */ 404210284Sjmallett result.u64 = 0; 405210284Sjmallett return result; 406210284Sjmallett } 407210284Sjmallett else 408210284Sjmallett { 409210284Sjmallett /* Ports 0 and 1 connect to the switch */ 410210284Sjmallett result.s.link_up = 1; 411210284Sjmallett result.s.full_duplex = 1; 412210284Sjmallett result.s.speed = 1000; 413210284Sjmallett return result; 414210284Sjmallett } 415210284Sjmallett break; 416210311Sjmallett /* Private vendor-defined boards. */ 417210311Sjmallett#if defined(OCTEON_VENDOR_LANNER) 418215014Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR730: 419215014Sjmallett /* Ports are BCM5482S */ 420215014Sjmallett is_broadcom_phy = 1; 421215014Sjmallett break; 422210311Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR320: 423216476Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR321X: 424210311Sjmallett /* Port 0 connects to the switch */ 425210311Sjmallett if (ipd_port == 0) 426210311Sjmallett { 427210311Sjmallett result.s.link_up = 1; 428210311Sjmallett result.s.full_duplex = 1; 429210311Sjmallett result.s.speed = 1000; 430210311Sjmallett return result; 431210311Sjmallett } 432210311Sjmallett break; 433210311Sjmallett#endif 434210284Sjmallett } 435210311Sjmallett#endif 436210284Sjmallett 437210284Sjmallett phy_addr = cvmx_helper_board_get_mii_address(ipd_port); 438210284Sjmallett if (phy_addr != -1) 439210284Sjmallett { 440210284Sjmallett if (is_broadcom_phy) 441210284Sjmallett { 442210284Sjmallett /* Below we are going to read SMI/MDIO register 0x19 which works 443210284Sjmallett on Broadcom parts */ 444210284Sjmallett int phy_status = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 0x19); 445210284Sjmallett switch ((phy_status>>8) & 0x7) 446210284Sjmallett { 447210284Sjmallett case 0: 448210284Sjmallett result.u64 = 0; 449210284Sjmallett break; 450210284Sjmallett case 1: 451210284Sjmallett result.s.link_up = 1; 452210284Sjmallett result.s.full_duplex = 0; 453210284Sjmallett result.s.speed = 10; 454210284Sjmallett break; 455210284Sjmallett case 2: 456210284Sjmallett result.s.link_up = 1; 457210284Sjmallett result.s.full_duplex = 1; 458210284Sjmallett result.s.speed = 10; 459210284Sjmallett break; 460210284Sjmallett case 3: 461210284Sjmallett result.s.link_up = 1; 462210284Sjmallett result.s.full_duplex = 0; 463210284Sjmallett result.s.speed = 100; 464210284Sjmallett break; 465210284Sjmallett case 4: 466210284Sjmallett result.s.link_up = 1; 467210284Sjmallett result.s.full_duplex = 1; 468210284Sjmallett result.s.speed = 100; 469210284Sjmallett break; 470210284Sjmallett case 5: 471210284Sjmallett result.s.link_up = 1; 472210284Sjmallett result.s.full_duplex = 1; 473210284Sjmallett result.s.speed = 100; 474210284Sjmallett break; 475210284Sjmallett case 6: 476210284Sjmallett result.s.link_up = 1; 477210284Sjmallett result.s.full_duplex = 0; 478210284Sjmallett result.s.speed = 1000; 479210284Sjmallett break; 480210284Sjmallett case 7: 481210284Sjmallett result.s.link_up = 1; 482210284Sjmallett result.s.full_duplex = 1; 483210284Sjmallett result.s.speed = 1000; 484210284Sjmallett break; 485210284Sjmallett } 486210284Sjmallett } 487210284Sjmallett else 488210284Sjmallett { 489210284Sjmallett /* This code assumes we are using a Marvell Gigabit PHY. All the 490210284Sjmallett speed information can be read from register 17 in one go. Somebody 491210284Sjmallett using a different PHY will need to handle it above in the board 492210284Sjmallett specific area */ 493210284Sjmallett int phy_status = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 17); 494210284Sjmallett 495210284Sjmallett /* If the resolve bit 11 isn't set, see if autoneg is turned off 496210284Sjmallett (bit 12, reg 0). The resolve bit doesn't get set properly when 497210284Sjmallett autoneg is off, so force it */ 498210284Sjmallett if ((phy_status & (1<<11)) == 0) 499210284Sjmallett { 500210284Sjmallett int auto_status = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 0); 501210284Sjmallett if ((auto_status & (1<<12)) == 0) 502210284Sjmallett phy_status |= 1<<11; 503210284Sjmallett } 504210284Sjmallett 505210284Sjmallett /* Only return a link if the PHY has finished auto negotiation 506210284Sjmallett and set the resolved bit (bit 11) */ 507210284Sjmallett if (phy_status & (1<<11)) 508210284Sjmallett { 509210311Sjmallett#if defined(OCTEON_BOARD_CAPK_0100ND) 510210311Sjmallett result.s.link_up = (phy_status>>10)&1; 511210311Sjmallett#else 512210284Sjmallett result.s.link_up = 1; 513210311Sjmallett#endif 514210284Sjmallett result.s.full_duplex = ((phy_status>>13)&1); 515210284Sjmallett switch ((phy_status>>14)&3) 516210284Sjmallett { 517210284Sjmallett case 0: /* 10 Mbps */ 518210284Sjmallett result.s.speed = 10; 519210284Sjmallett break; 520210284Sjmallett case 1: /* 100 Mbps */ 521210284Sjmallett result.s.speed = 100; 522210284Sjmallett break; 523210284Sjmallett case 2: /* 1 Gbps */ 524210284Sjmallett result.s.speed = 1000; 525210284Sjmallett break; 526210284Sjmallett case 3: /* Illegal */ 527210284Sjmallett result.u64 = 0; 528210284Sjmallett break; 529210284Sjmallett } 530210284Sjmallett } 531210284Sjmallett } 532210284Sjmallett } 533210284Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN58XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) 534210284Sjmallett { 535210284Sjmallett /* We don't have a PHY address, so attempt to use in-band status. It is 536210284Sjmallett really important that boards not supporting in-band status never get 537210284Sjmallett here. Reading broken in-band status tends to do bad things */ 538210284Sjmallett cvmx_gmxx_rxx_rx_inbnd_t inband_status; 539210284Sjmallett int interface = cvmx_helper_get_interface_num(ipd_port); 540210284Sjmallett int index = cvmx_helper_get_interface_index_num(ipd_port); 541210284Sjmallett inband_status.u64 = cvmx_read_csr(CVMX_GMXX_RXX_RX_INBND(index, interface)); 542210284Sjmallett 543210284Sjmallett result.s.link_up = inband_status.s.status; 544210284Sjmallett result.s.full_duplex = inband_status.s.duplex; 545210284Sjmallett switch (inband_status.s.speed) 546210284Sjmallett { 547210284Sjmallett case 0: /* 10 Mbps */ 548210284Sjmallett result.s.speed = 10; 549210284Sjmallett break; 550210284Sjmallett case 1: /* 100 Mbps */ 551210284Sjmallett result.s.speed = 100; 552210284Sjmallett break; 553210284Sjmallett case 2: /* 1 Gbps */ 554210284Sjmallett result.s.speed = 1000; 555210284Sjmallett break; 556210284Sjmallett case 3: /* Illegal */ 557210284Sjmallett result.u64 = 0; 558210284Sjmallett break; 559210284Sjmallett } 560210284Sjmallett } 561210284Sjmallett else 562210284Sjmallett { 563210284Sjmallett /* We don't have a PHY address and we don't have in-band status. There 564210284Sjmallett is no way to determine the link speed. Return down assuming this 565210284Sjmallett port isn't wired */ 566210284Sjmallett result.u64 = 0; 567210284Sjmallett } 568210284Sjmallett 569210284Sjmallett /* If link is down, return all fields as zero. */ 570210284Sjmallett if (!result.s.link_up) 571210284Sjmallett result.u64 = 0; 572210284Sjmallett 573210284Sjmallett return result; 574210284Sjmallett} 575210284Sjmallett 576210284Sjmallett 577210284Sjmallett/** 578210284Sjmallett * This function as a board specific method of changing the PHY 579215990Sjmallett * speed, duplex, and autonegotiation. This programs the PHY and 580210284Sjmallett * not Octeon. This can be used to force Octeon's links to 581210284Sjmallett * specific settings. 582210284Sjmallett * 583210284Sjmallett * @param phy_addr The address of the PHY to program 584215990Sjmallett * @param link_flags 585215990Sjmallett * Flags to control autonegotiation. Bit 0 is autonegotiation 586215990Sjmallett * enable/disable to maintain backward compatibility. 587215990Sjmallett * @param link_info Link speed to program. If the speed is zero and autonegotiation 588210284Sjmallett * is enabled, all possible negotiation speeds are advertised. 589210284Sjmallett * 590210284Sjmallett * @return Zero on success, negative on failure 591210284Sjmallett */ 592210284Sjmallettint cvmx_helper_board_link_set_phy(int phy_addr, cvmx_helper_board_set_phy_link_flags_types_t link_flags, 593210284Sjmallett cvmx_helper_link_info_t link_info) 594210284Sjmallett{ 595210284Sjmallett 596210284Sjmallett /* Set the flow control settings based on link_flags */ 597210284Sjmallett if ((link_flags & set_phy_link_flags_flow_control_mask) != set_phy_link_flags_flow_control_dont_touch) 598210284Sjmallett { 599210284Sjmallett cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; 600210284Sjmallett reg_autoneg_adver.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER); 601210284Sjmallett reg_autoneg_adver.s.asymmetric_pause = (link_flags & set_phy_link_flags_flow_control_mask) == set_phy_link_flags_flow_control_enable; 602210284Sjmallett reg_autoneg_adver.s.pause = (link_flags & set_phy_link_flags_flow_control_mask) == set_phy_link_flags_flow_control_enable; 603210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER, reg_autoneg_adver.u16); 604210284Sjmallett } 605210284Sjmallett 606210284Sjmallett /* If speed isn't set and autoneg is on advertise all supported modes */ 607210284Sjmallett if ((link_flags & set_phy_link_flags_autoneg) && (link_info.s.speed == 0)) 608210284Sjmallett { 609210284Sjmallett cvmx_mdio_phy_reg_control_t reg_control; 610210284Sjmallett cvmx_mdio_phy_reg_status_t reg_status; 611210284Sjmallett cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; 612210284Sjmallett cvmx_mdio_phy_reg_extended_status_t reg_extended_status; 613210284Sjmallett cvmx_mdio_phy_reg_control_1000_t reg_control_1000; 614210284Sjmallett 615210284Sjmallett reg_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_STATUS); 616210284Sjmallett reg_autoneg_adver.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER); 617210284Sjmallett reg_autoneg_adver.s.advert_100base_t4 = reg_status.s.capable_100base_t4; 618210284Sjmallett reg_autoneg_adver.s.advert_10base_tx_full = reg_status.s.capable_10_full; 619210284Sjmallett reg_autoneg_adver.s.advert_10base_tx_half = reg_status.s.capable_10_half; 620210284Sjmallett reg_autoneg_adver.s.advert_100base_tx_full = reg_status.s.capable_100base_x_full; 621210284Sjmallett reg_autoneg_adver.s.advert_100base_tx_half = reg_status.s.capable_100base_x_half; 622210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER, reg_autoneg_adver.u16); 623210284Sjmallett if (reg_status.s.capable_extended_status) 624210284Sjmallett { 625210284Sjmallett reg_extended_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_EXTENDED_STATUS); 626210284Sjmallett reg_control_1000.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000); 627210284Sjmallett reg_control_1000.s.advert_1000base_t_full = reg_extended_status.s.capable_1000base_t_full; 628210284Sjmallett reg_control_1000.s.advert_1000base_t_half = reg_extended_status.s.capable_1000base_t_half; 629210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000, reg_control_1000.u16); 630210284Sjmallett } 631210284Sjmallett reg_control.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL); 632210284Sjmallett reg_control.s.autoneg_enable = 1; 633210284Sjmallett reg_control.s.restart_autoneg = 1; 634210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); 635210284Sjmallett } 636210284Sjmallett else if ((link_flags & set_phy_link_flags_autoneg)) 637210284Sjmallett { 638210284Sjmallett cvmx_mdio_phy_reg_control_t reg_control; 639210284Sjmallett cvmx_mdio_phy_reg_status_t reg_status; 640210284Sjmallett cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; 641210284Sjmallett cvmx_mdio_phy_reg_extended_status_t reg_extended_status; 642210284Sjmallett cvmx_mdio_phy_reg_control_1000_t reg_control_1000; 643210284Sjmallett 644210284Sjmallett reg_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_STATUS); 645210284Sjmallett reg_autoneg_adver.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER); 646210284Sjmallett reg_autoneg_adver.s.advert_100base_t4 = 0; 647210284Sjmallett reg_autoneg_adver.s.advert_10base_tx_full = 0; 648210284Sjmallett reg_autoneg_adver.s.advert_10base_tx_half = 0; 649210284Sjmallett reg_autoneg_adver.s.advert_100base_tx_full = 0; 650210284Sjmallett reg_autoneg_adver.s.advert_100base_tx_half = 0; 651210284Sjmallett if (reg_status.s.capable_extended_status) 652210284Sjmallett { 653210284Sjmallett reg_extended_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_EXTENDED_STATUS); 654210284Sjmallett reg_control_1000.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000); 655210284Sjmallett reg_control_1000.s.advert_1000base_t_full = 0; 656210284Sjmallett reg_control_1000.s.advert_1000base_t_half = 0; 657210284Sjmallett } 658210284Sjmallett switch (link_info.s.speed) 659210284Sjmallett { 660210284Sjmallett case 10: 661210284Sjmallett reg_autoneg_adver.s.advert_10base_tx_full = link_info.s.full_duplex; 662210284Sjmallett reg_autoneg_adver.s.advert_10base_tx_half = !link_info.s.full_duplex; 663210284Sjmallett break; 664210284Sjmallett case 100: 665210284Sjmallett reg_autoneg_adver.s.advert_100base_tx_full = link_info.s.full_duplex; 666210284Sjmallett reg_autoneg_adver.s.advert_100base_tx_half = !link_info.s.full_duplex; 667210284Sjmallett break; 668210284Sjmallett case 1000: 669210284Sjmallett reg_control_1000.s.advert_1000base_t_full = link_info.s.full_duplex; 670210284Sjmallett reg_control_1000.s.advert_1000base_t_half = !link_info.s.full_duplex; 671210284Sjmallett break; 672210284Sjmallett } 673210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER, reg_autoneg_adver.u16); 674210284Sjmallett if (reg_status.s.capable_extended_status) 675210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000, reg_control_1000.u16); 676210284Sjmallett reg_control.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL); 677210284Sjmallett reg_control.s.autoneg_enable = 1; 678210284Sjmallett reg_control.s.restart_autoneg = 1; 679210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); 680210284Sjmallett } 681210284Sjmallett else 682210284Sjmallett { 683210284Sjmallett cvmx_mdio_phy_reg_control_t reg_control; 684210284Sjmallett reg_control.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL); 685210284Sjmallett reg_control.s.autoneg_enable = 0; 686210284Sjmallett reg_control.s.restart_autoneg = 1; 687210284Sjmallett reg_control.s.duplex = link_info.s.full_duplex; 688210284Sjmallett if (link_info.s.speed == 1000) 689210284Sjmallett { 690210284Sjmallett reg_control.s.speed_msb = 1; 691210284Sjmallett reg_control.s.speed_lsb = 0; 692210284Sjmallett } 693210284Sjmallett else if (link_info.s.speed == 100) 694210284Sjmallett { 695210284Sjmallett reg_control.s.speed_msb = 0; 696210284Sjmallett reg_control.s.speed_lsb = 1; 697210284Sjmallett } 698210284Sjmallett else if (link_info.s.speed == 10) 699210284Sjmallett { 700210284Sjmallett reg_control.s.speed_msb = 0; 701210284Sjmallett reg_control.s.speed_lsb = 0; 702210284Sjmallett } 703210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); 704210284Sjmallett } 705210284Sjmallett return 0; 706210284Sjmallett} 707210284Sjmallett 708210284Sjmallett 709210284Sjmallett/** 710210284Sjmallett * @INTERNAL 711210284Sjmallett * This function is called by cvmx_helper_interface_probe() after it 712210284Sjmallett * determines the number of ports Octeon can support on a specific 713210284Sjmallett * interface. This function is the per board location to override 714210284Sjmallett * this value. It is called with the number of ports Octeon might 715210284Sjmallett * support and should return the number of actual ports on the 716210284Sjmallett * board. 717210284Sjmallett * 718215990Sjmallett * This function must be modified for every new Octeon board. 719210284Sjmallett * Internally it uses switch statements based on the cvmx_sysinfo 720215990Sjmallett * data to determine board types and revisions. It relies on the 721210284Sjmallett * fact that every Octeon board receives a unique board type 722210284Sjmallett * enumeration from the bootloader. 723210284Sjmallett * 724210284Sjmallett * @param interface Interface to probe 725210284Sjmallett * @param supported_ports 726210284Sjmallett * Number of ports Octeon supports. 727210284Sjmallett * 728210284Sjmallett * @return Number of ports the actual board supports. Many times this will 729210284Sjmallett * simple be "support_ports". 730210284Sjmallett */ 731210284Sjmallettint __cvmx_helper_board_interface_probe(int interface, int supported_ports) 732210284Sjmallett{ 733210284Sjmallett switch (cvmx_sysinfo_get()->board_type) 734210284Sjmallett { 735210284Sjmallett case CVMX_BOARD_TYPE_CN3005_EVB_HS5: 736215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_A: 737215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_U: 738215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_G: 739210284Sjmallett if (interface == 0) 740210284Sjmallett return 2; 741210284Sjmallett break; 742210284Sjmallett case CVMX_BOARD_TYPE_BBGW_REF: 743210284Sjmallett if (interface == 0) 744210284Sjmallett return 2; 745210284Sjmallett break; 746210284Sjmallett case CVMX_BOARD_TYPE_NIC_XLE_4G: 747210284Sjmallett if (interface == 0) 748210284Sjmallett return 0; 749210284Sjmallett break; 750210284Sjmallett /* The 2nd interface on the EBH5600 is connected to the Marvel switch, 751210284Sjmallett which we don't support. Disable ports connected to it */ 752210284Sjmallett case CVMX_BOARD_TYPE_EBH5600: 753210284Sjmallett if (interface == 1) 754210284Sjmallett return 0; 755210284Sjmallett break; 756215990Sjmallett case CVMX_BOARD_TYPE_EBB5600: 757215990Sjmallett#ifdef CVMX_ENABLE_PKO_FUNCTIONS 758215990Sjmallett if (cvmx_helper_interface_get_mode(interface) == CVMX_HELPER_INTERFACE_MODE_PICMG) 759215990Sjmallett return 0; 760215990Sjmallett#endif 761215990Sjmallett break; 762215990Sjmallett case CVMX_BOARD_TYPE_EBT5810: 763215990Sjmallett return 1; /* Two ports on each SPI: 1 hooked to MAC, 1 loopback 764215990Sjmallett ** Loopback disabled by default. */ 765212844Sjmallett#if defined(OCTEON_VENDOR_LANNER) 766212844Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR955: 767212844Sjmallett if (interface == 1) 768212844Sjmallett return 12; 769212844Sjmallett break; 770212844Sjmallett#endif 771210284Sjmallett } 772210284Sjmallett#ifdef CVMX_BUILD_FOR_UBOOT 773210284Sjmallett if (CVMX_HELPER_INTERFACE_MODE_SPI == cvmx_helper_interface_get_mode(interface) && getenv("disable_spi")) 774210284Sjmallett return 0; 775210284Sjmallett#endif 776210284Sjmallett return supported_ports; 777210284Sjmallett} 778210284Sjmallett 779210284Sjmallett 780210284Sjmallett/** 781210284Sjmallett * @INTERNAL 782210284Sjmallett * Enable packet input/output from the hardware. This function is 783210284Sjmallett * called after by cvmx_helper_packet_hardware_enable() to 784210284Sjmallett * perform board specific initialization. For most boards 785210284Sjmallett * nothing is needed. 786210284Sjmallett * 787210284Sjmallett * @param interface Interface to enable 788210284Sjmallett * 789210284Sjmallett * @return Zero on success, negative on failure 790210284Sjmallett */ 791210284Sjmallettint __cvmx_helper_board_hardware_enable(int interface) 792210284Sjmallett{ 793210284Sjmallett if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5) 794210284Sjmallett { 795210284Sjmallett if (interface == 0) 796210284Sjmallett { 797210284Sjmallett /* Different config for switch port */ 798210284Sjmallett cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(1, interface), 0); 799210284Sjmallett cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(1, interface), 0); 800210284Sjmallett /* Boards with gigabit WAN ports need a different setting that is 801210284Sjmallett compatible with 100 Mbit settings */ 802210284Sjmallett cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 0xc); 803210284Sjmallett cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 0xc); 804210284Sjmallett } 805210284Sjmallett } 806215990Sjmallett else if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_LANAI2_U) 807215990Sjmallett { 808215990Sjmallett if (interface == 0) 809215990Sjmallett { 810215990Sjmallett cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 16); 811215990Sjmallett cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 16); 812215990Sjmallett } 813215990Sjmallett } 814210284Sjmallett else if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3010_EVB_HS5) 815210284Sjmallett { 816215990Sjmallett /* Broadcom PHYs require different ASX clocks. Unfortunately 817210284Sjmallett many customer don't define a new board Id and simply 818210284Sjmallett mangle the CN3010_EVB_HS5 */ 819210284Sjmallett if (interface == 0) 820210284Sjmallett { 821210284Sjmallett /* Some customers boards use a hacked up bootloader that identifies them as 822210284Sjmallett ** CN3010_EVB_HS5 evaluation boards. This leads to all kinds of configuration 823210284Sjmallett ** problems. Detect one case, and print warning, while trying to do the right thing. 824210284Sjmallett */ 825210284Sjmallett int phy_addr = cvmx_helper_board_get_mii_address(0); 826210284Sjmallett if (phy_addr != -1) 827210284Sjmallett { 828210284Sjmallett int phy_identifier = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 0x2); 829210284Sjmallett /* Is it a Broadcom PHY? */ 830210284Sjmallett if (phy_identifier == 0x0143) 831210284Sjmallett { 832210284Sjmallett cvmx_dprintf("\n"); 833210284Sjmallett cvmx_dprintf("ERROR:\n"); 834210284Sjmallett cvmx_dprintf("ERROR: Board type is CVMX_BOARD_TYPE_CN3010_EVB_HS5, but Broadcom PHY found.\n"); 835210284Sjmallett cvmx_dprintf("ERROR: The board type is mis-configured, and software malfunctions are likely.\n"); 836210284Sjmallett cvmx_dprintf("ERROR: All boards require a unique board type to identify them.\n"); 837210284Sjmallett cvmx_dprintf("ERROR:\n"); 838210284Sjmallett cvmx_dprintf("\n"); 839210284Sjmallett cvmx_wait(1000000000); 840210284Sjmallett cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 5); 841210284Sjmallett cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 5); 842210284Sjmallett } 843210284Sjmallett } 844210284Sjmallett } 845210284Sjmallett } 846210284Sjmallett return 0; 847210284Sjmallett} 848210284Sjmallett 849215990Sjmallett 850215990Sjmallett/** 851215990Sjmallett * @INTERNAL 852215990Sjmallett * Gets the clock type used for the USB block based on board type. 853215990Sjmallett * Used by the USB code for auto configuration of clock type. 854215990Sjmallett * 855215990Sjmallett * @return USB clock type enumeration 856215990Sjmallett */ 857210284Sjmallettcvmx_helper_board_usb_clock_types_t __cvmx_helper_board_usb_get_clock_type(void) 858210284Sjmallett{ 859215990Sjmallett switch (cvmx_sysinfo_get()->board_type) 860215990Sjmallett { 861215990Sjmallett case CVMX_BOARD_TYPE_BBGW_REF: 862215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_A: 863215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_U: 864215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_G: 865210311Sjmallett#if defined(OCTEON_VENDOR_LANNER) 866210311Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR320: 867216476Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR321X: 868210311Sjmallett#endif 869210284Sjmallett return USB_CLOCK_TYPE_CRYSTAL_12; 870210284Sjmallett } 871210284Sjmallett return USB_CLOCK_TYPE_REF_48; 872210284Sjmallett} 873210284Sjmallett 874215990Sjmallett 875215990Sjmallett/** 876215990Sjmallett * @INTERNAL 877215990Sjmallett * Adjusts the number of available USB ports on Octeon based on board 878215990Sjmallett * specifics. 879215990Sjmallett * 880215990Sjmallett * @param supported_ports expected number of ports based on chip type; 881215990Sjmallett * 882215990Sjmallett * 883215990Sjmallett * @return number of available usb ports, based on board specifics. 884215990Sjmallett * Return value is supported_ports if function does not 885215990Sjmallett * override. 886215990Sjmallett */ 887210284Sjmallettint __cvmx_helper_board_usb_get_num_ports(int supported_ports) 888210284Sjmallett{ 889215990Sjmallett switch (cvmx_sysinfo_get()->board_type) 890215990Sjmallett { 891210284Sjmallett case CVMX_BOARD_TYPE_NIC_XLE_4G: 892210284Sjmallett return 0; 893210284Sjmallett } 894210284Sjmallett 895210284Sjmallett return supported_ports; 896210284Sjmallett} 897210284Sjmallett 898210284Sjmallett 899