1210284Sjmallett/***********************license start*************** 2232812Sjmallett * Copyright (c) 2003-2011 Cavium Inc. (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 18232812Sjmallett * * Neither the name of Cavium Inc. 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" 29232812Sjmallett * AND WITH ALL FAULTS AND CAVIUM INC. 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 * 52232812Sjmallett * <hr>$Revision: 70030 $<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" 75232812Sjmallett#include "cvmx-gpio.h" 76232815Sjmallett#if !defined(__FreeBSD__) || !defined(_KERNEL) 77232812Sjmallett#ifdef __U_BOOT__ 78232812Sjmallett# include <libfdt.h> 79232812Sjmallett#else 80232812Sjmallett# include "libfdt/libfdt.h" 81215990Sjmallett#endif 82232815Sjmallett#endif 83232812Sjmallett#include "cvmx-swap.h" 84232812Sjmallett#endif 85210284Sjmallett 86210284Sjmallett/** 87210284Sjmallett * cvmx_override_board_link_get(int ipd_port) is a function 88210284Sjmallett * pointer. It is meant to allow customization of the process of 89210284Sjmallett * talking to a PHY to determine link speed. It is called every 90210284Sjmallett * time a PHY must be polled for link status. Users should set 91210284Sjmallett * this pointer to a function before calling any cvmx-helper 92210284Sjmallett * operations. 93210284Sjmallett */ 94210284SjmallettCVMX_SHARED cvmx_helper_link_info_t (*cvmx_override_board_link_get)(int ipd_port) = NULL; 95210284Sjmallett 96232812Sjmallett#if !defined(CVMX_BUILD_FOR_LINUX_KERNEL) && (!defined(__FreeBSD__) || !defined(_KERNEL)) 97232812Sjmallett 98232812Sjmallettstatic void cvmx_retry_i2c_write(int twsi_id, uint8_t dev_addr, uint16_t internal_addr, int num_bytes, int ia_width_bytes, uint64_t data) 99232812Sjmallett{ 100232812Sjmallett int tries = 3; 101232812Sjmallett int r; 102232812Sjmallett do { 103232812Sjmallett r = cvmx_twsix_write_ia(twsi_id, dev_addr, internal_addr, num_bytes, ia_width_bytes, data); 104232812Sjmallett } while (tries-- > 0 && r < 0); 105232812Sjmallett} 106232812Sjmallett 107232812Sjmallettstatic int __pip_eth_node(const void *fdt_addr, int aliases, int ipd_port) 108232812Sjmallett{ 109232812Sjmallett char name_buffer[20]; 110232812Sjmallett const char*pip_path; 111232812Sjmallett int pip, iface, eth; 112232812Sjmallett int interface_num = cvmx_helper_get_interface_num(ipd_port); 113232812Sjmallett int interface_index = cvmx_helper_get_interface_index_num(ipd_port); 114232812Sjmallett 115232812Sjmallett pip_path = fdt_getprop(fdt_addr, aliases, "pip", NULL); 116232812Sjmallett if (!pip_path) 117232812Sjmallett { 118232812Sjmallett cvmx_dprintf("ERROR: pip path not found in device tree\n"); 119232812Sjmallett return -1; 120232812Sjmallett } 121232812Sjmallett pip = fdt_path_offset(fdt_addr, pip_path); 122232812Sjmallett if (pip < 0) 123232812Sjmallett { 124232812Sjmallett cvmx_dprintf("ERROR: pip not found in device tree\n"); 125232812Sjmallett return -1; 126232812Sjmallett } 127232812Sjmallett#ifdef __U_BOOT__ 128232812Sjmallett sprintf(name_buffer, "interface@%d", interface_num); 129232812Sjmallett#else 130232812Sjmallett snprintf(name_buffer, sizeof(name_buffer), "interface@%d", interface_num); 131232812Sjmallett#endif 132232812Sjmallett iface = fdt_subnode_offset(fdt_addr, pip, name_buffer); 133232812Sjmallett if (iface < 0) 134232812Sjmallett { 135232812Sjmallett cvmx_dprintf("ERROR : pip intf %d not found in device tree \n", 136232812Sjmallett interface_num); 137232812Sjmallett return -1; 138232812Sjmallett } 139232812Sjmallett#ifdef __U_BOOT__ 140232812Sjmallett sprintf(name_buffer, "ethernet@%x", interface_index); 141232812Sjmallett#else 142232812Sjmallett snprintf(name_buffer, sizeof(name_buffer), "ethernet@%x", interface_index); 143232812Sjmallett#endif 144232812Sjmallett eth = fdt_subnode_offset(fdt_addr, iface, name_buffer); 145232812Sjmallett if (eth < 0) 146232812Sjmallett { 147232812Sjmallett cvmx_dprintf("ERROR : pip interface@%d ethernet@%d not found in device " 148232812Sjmallett "tree\n", interface_num, interface_index); 149232812Sjmallett return -1; 150232812Sjmallett } 151232812Sjmallett return eth; 152232812Sjmallett} 153232812Sjmallett 154232812Sjmallettstatic int __mix_eth_node(const void *fdt_addr, int aliases, int interface_index) 155232812Sjmallett{ 156232812Sjmallett char name_buffer[20]; 157232812Sjmallett const char*mix_path; 158232812Sjmallett int mix; 159232812Sjmallett 160232812Sjmallett#ifdef __U_BOOT__ 161232812Sjmallett sprintf(name_buffer, "mix%d", interface_index); 162232812Sjmallett#else 163232812Sjmallett snprintf(name_buffer, sizeof(name_buffer), "mix%d", interface_index); 164232812Sjmallett#endif 165232812Sjmallett mix_path = fdt_getprop(fdt_addr, aliases, name_buffer, NULL); 166232812Sjmallett if (!mix_path) 167232812Sjmallett { 168232812Sjmallett cvmx_dprintf("ERROR: mix%d path not found in device tree\n",interface_index); 169232812Sjmallett } 170232812Sjmallett mix = fdt_path_offset(fdt_addr, mix_path); 171232812Sjmallett if (mix < 0) 172232812Sjmallett { 173232812Sjmallett cvmx_dprintf("ERROR: %s not found in device tree\n", mix_path); 174232812Sjmallett return -1; 175232812Sjmallett } 176232812Sjmallett return mix; 177232812Sjmallett} 178232812Sjmallett 179232812Sjmalletttypedef struct cvmx_phy_info 180232812Sjmallett{ 181232812Sjmallett int phy_addr; 182232812Sjmallett int direct_connect; 183232812Sjmallett cvmx_phy_type_t phy_type; 184232812Sjmallett}cvmx_phy_info_t; 185232812Sjmallett 186232812Sjmallett 187232812Sjmallettstatic int __mdiobus_addr_to_unit(uint32_t addr) 188232812Sjmallett{ 189232812Sjmallett int unit = (addr >> 7) & 3; 190232812Sjmallett if (!OCTEON_IS_MODEL(OCTEON_CN68XX)) 191232812Sjmallett unit >>= 1; 192232812Sjmallett return unit; 193232812Sjmallett} 194210284Sjmallett/** 195210284Sjmallett * Return the MII PHY address associated with the given IPD 196232812Sjmallett * port. The phy address is obtained from the device tree. 197232812Sjmallett * 198232812Sjmallett * @param ipd_port Octeon IPD port to get the MII address for. 199232812Sjmallett * 200232812Sjmallett * @return MII PHY address and bus number or -1. 201232812Sjmallett */ 202232812Sjmallett 203232812Sjmallettstatic cvmx_phy_info_t __get_phy_info_from_dt(int ipd_port) 204232812Sjmallett{ 205232812Sjmallett const void *fdt_addr = CASTPTR(const void *, cvmx_sysinfo_get()->fdt_addr); 206232812Sjmallett uint32_t *phy_handle; 207232812Sjmallett int aliases, eth, phy, phy_parent, phandle, ret; 208232812Sjmallett cvmx_phy_info_t phy_info; 209232812Sjmallett int mdio_unit=-1; 210232812Sjmallett const char *phy_comaptible_str; 211232812Sjmallett uint32_t *phy_addr_ptr; 212232812Sjmallett 213232812Sjmallett phy_info.phy_addr = -1; 214232812Sjmallett phy_info.direct_connect = -1; 215232812Sjmallett phy_info.phy_type = (cvmx_phy_type_t) -1; 216232812Sjmallett 217232812Sjmallett if (!fdt_addr) 218232812Sjmallett { 219232812Sjmallett cvmx_dprintf("No device tree found.\n"); 220232812Sjmallett return phy_info; 221232812Sjmallett } 222232812Sjmallett aliases = fdt_path_offset(fdt_addr, "/aliases"); 223232812Sjmallett if (aliases < 0) { 224232812Sjmallett cvmx_dprintf("Error: No /aliases node in device tree.\n"); 225232812Sjmallett return phy_info; 226232812Sjmallett } 227232812Sjmallett if (ipd_port < 0) 228232812Sjmallett { 229232812Sjmallett int interface_index = ipd_port - CVMX_HELPER_BOARD_MGMT_IPD_PORT; 230232812Sjmallett eth = __mix_eth_node(fdt_addr, aliases, interface_index) ; 231232812Sjmallett } 232232812Sjmallett else 233232812Sjmallett { 234232812Sjmallett eth = __pip_eth_node(fdt_addr, aliases, ipd_port); 235232812Sjmallett } 236232812Sjmallett if (eth < 0 ) 237232812Sjmallett { 238232812Sjmallett cvmx_dprintf("ERROR : cannot find interface for ipd_port=%d\n", ipd_port); 239232812Sjmallett return phy_info; 240232812Sjmallett } 241232812Sjmallett /* Get handle to phy */ 242232812Sjmallett phy_handle = (uint32_t *) fdt_getprop(fdt_addr, eth, "phy-handle", NULL); 243232812Sjmallett if (!phy_handle) 244232812Sjmallett { 245232812Sjmallett cvmx_dprintf("ERROR : phy handle not found in device tree ipd_port=%d" 246232812Sjmallett "\n", ipd_port); 247232812Sjmallett return phy_info; 248232812Sjmallett } 249232812Sjmallett phandle = cvmx_be32_to_cpu(*phy_handle); 250232812Sjmallett phy = fdt_node_offset_by_phandle(fdt_addr, phandle); 251232812Sjmallett if (phy < 0) 252232812Sjmallett { 253232812Sjmallett cvmx_dprintf("ERROR : cannot find phy for ipd_port=%d ret=%d\n", 254232812Sjmallett ipd_port, phy); 255232812Sjmallett return phy_info; 256232812Sjmallett } 257232812Sjmallett phy_comaptible_str = (const char *) fdt_getprop(fdt_addr, phy, 258232812Sjmallett "compatible", NULL); 259232812Sjmallett if (!phy_comaptible_str) 260232812Sjmallett { 261232812Sjmallett cvmx_dprintf("ERROR : no compatible prop in phy\n"); 262232812Sjmallett return phy_info; 263232812Sjmallett } 264232812Sjmallett if (memcmp("marvell", phy_comaptible_str, strlen("marvell")) == 0) 265232812Sjmallett { 266232812Sjmallett phy_info.phy_type = MARVELL_GENERIC_PHY; 267232812Sjmallett } 268232812Sjmallett else if (memcmp("broadcom", phy_comaptible_str, strlen("broadcom")) == 0) 269232812Sjmallett { 270232812Sjmallett phy_info.phy_type = BROADCOM_GENERIC_PHY; 271232812Sjmallett } 272232812Sjmallett else 273232812Sjmallett { 274232812Sjmallett phy_info.phy_type = -1; 275232812Sjmallett } 276232812Sjmallett 277232812Sjmallett /* Check if PHY parent is the octeon MDIO bus. Some boards are connected 278232812Sjmallett though a MUX and for them direct_connect_to_phy will be 0 */ 279232812Sjmallett phy_parent = fdt_parent_offset(fdt_addr, phy); 280232812Sjmallett if (phy_parent < 0) 281232812Sjmallett { 282232812Sjmallett cvmx_dprintf("ERROR : cannot find phy parent for ipd_port=%d ret=%d\n", 283232812Sjmallett ipd_port, phy_parent); 284232812Sjmallett return phy_info; 285232812Sjmallett } 286232812Sjmallett ret = fdt_node_check_compatible(fdt_addr, phy_parent, 287232812Sjmallett "cavium,octeon-3860-mdio"); 288232812Sjmallett if (ret == 0) 289232812Sjmallett { 290232812Sjmallett phy_info.direct_connect = 1 ; 291232812Sjmallett uint32_t *mdio_reg_base = (uint32_t *) fdt_getprop(fdt_addr, phy_parent,"reg",0); 292232812Sjmallett if (mdio_reg_base == 0) 293232812Sjmallett { 294232812Sjmallett cvmx_dprintf("ERROR : unable to get reg property in phy mdio\n"); 295232812Sjmallett return phy_info; 296232812Sjmallett } 297232812Sjmallett mdio_unit = __mdiobus_addr_to_unit(mdio_reg_base[1]); 298232812Sjmallett //cvmx_dprintf("phy parent=%s reg_base=%08x unit=%d \n", 299232812Sjmallett // fdt_get_name(fdt_addr,phy_parent, NULL), mdio_reg_base[1], mdio_unit); 300232812Sjmallett } 301232812Sjmallett else 302232812Sjmallett { 303232812Sjmallett phy_info.direct_connect = 0; 304232812Sjmallett /* The PHY is not directly connected to the Octeon MDIO bus. 305232812Sjmallett SE doesn't have abstractions for MDIO MUX or MDIO MUX drivers and 306232812Sjmallett hence for the non direct cases code will be needed which is 307232812Sjmallett board specific. 308232812Sjmallett For now the the MDIO Unit is defaulted to 1. 309232812Sjmallett */ 310232812Sjmallett mdio_unit = 1; 311232812Sjmallett } 312232812Sjmallett 313232812Sjmallett phy_addr_ptr = (uint32_t *) fdt_getprop(fdt_addr, phy, "reg", NULL); 314232812Sjmallett phy_info.phy_addr = cvmx_be32_to_cpu(*phy_addr_ptr) | mdio_unit << 8; 315232812Sjmallett return phy_info; 316232812Sjmallett 317232812Sjmallett} 318232812Sjmallett 319232812Sjmallett/** 320232812Sjmallett * Return the MII PHY address associated with the given IPD 321232812Sjmallett * port. The phy address is obtained from the device tree. 322232812Sjmallett * 323232812Sjmallett * @param ipd_port Octeon IPD port to get the MII address for. 324232812Sjmallett * 325232812Sjmallett * @return MII PHY address and bus number or -1. 326232812Sjmallett */ 327232812Sjmallett 328232812Sjmallettint cvmx_helper_board_get_mii_address_from_dt(int ipd_port) 329232812Sjmallett{ 330232812Sjmallett cvmx_phy_info_t phy_info = __get_phy_info_from_dt(ipd_port); 331232812Sjmallett return phy_info.phy_addr; 332232812Sjmallett} 333232812Sjmallett#endif 334232812Sjmallett 335232812Sjmallett/** 336232812Sjmallett * Return the MII PHY address associated with the given IPD 337210284Sjmallett * port. A result of -1 means there isn't a MII capable PHY 338210284Sjmallett * connected to this port. On chips supporting multiple MII 339210284Sjmallett * busses the bus number is encoded in bits <15:8>. 340210284Sjmallett * 341210284Sjmallett * This function must be modified for every new Octeon board. 342210284Sjmallett * Internally it uses switch statements based on the cvmx_sysinfo 343210284Sjmallett * data to determine board types and revisions. It replies on the 344210284Sjmallett * fact that every Octeon board receives a unique board type 345210284Sjmallett * enumeration from the bootloader. 346210284Sjmallett * 347210284Sjmallett * @param ipd_port Octeon IPD port to get the MII address for. 348210284Sjmallett * 349210284Sjmallett * @return MII PHY address and bus number or -1. 350210284Sjmallett */ 351210284Sjmallettint cvmx_helper_board_get_mii_address(int ipd_port) 352210284Sjmallett{ 353210311Sjmallett /* 354210311Sjmallett * Board types we have to know at compile-time. 355210311Sjmallett */ 356210311Sjmallett#ifdef OCTEON_BOARD_CAPK_0100ND 357210311Sjmallett switch (ipd_port) { 358210311Sjmallett case 0: 359210311Sjmallett return 2; 360210311Sjmallett case 1: 361210311Sjmallett return 3; 362210311Sjmallett case 2: 363210311Sjmallett /* XXX Switch PHY? */ 364210311Sjmallett return -1; 365210311Sjmallett default: 366210311Sjmallett return -1; 367210311Sjmallett } 368210311Sjmallett#endif 369210311Sjmallett 370210311Sjmallett /* 371210311Sjmallett * For board types we can determine at runtime. 372210311Sjmallett */ 373232812Sjmallett if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) 374232812Sjmallett return -1; 375232812Sjmallett#if !defined(CVMX_BUILD_FOR_LINUX_KERNEL) && (!defined(__FreeBSD__) || !defined(_KERNEL)) 376232812Sjmallett if (cvmx_sysinfo_get()->fdt_addr) 377232812Sjmallett { 378232812Sjmallett cvmx_phy_info_t phy_info = __get_phy_info_from_dt(ipd_port); 379232812Sjmallett //cvmx_dprintf("ipd_port=%d phy_addr=%d\n", ipd_port, phy_info.phy_addr); 380232812Sjmallett if (phy_info.phy_addr >= 0) return phy_info.phy_addr; 381232812Sjmallett } 382232812Sjmallett#endif 383210284Sjmallett switch (cvmx_sysinfo_get()->board_type) 384210284Sjmallett { 385210284Sjmallett case CVMX_BOARD_TYPE_SIM: 386210284Sjmallett /* Simulator doesn't have MII */ 387210284Sjmallett return -1; 388250428Simp#if !defined(OCTEON_VENDOR_GEFES) 389250428Simp case CVMX_BOARD_TYPE_EBT5800: 390250428Simp case CVMX_BOARD_TYPE_NICPRO2: 391250428Simp#endif 392210284Sjmallett case CVMX_BOARD_TYPE_EBT3000: 393210284Sjmallett case CVMX_BOARD_TYPE_THUNDER: 394210284Sjmallett /* Interface 0 is SPI4, interface 1 is RGMII */ 395210284Sjmallett if ((ipd_port >= 16) && (ipd_port < 20)) 396210284Sjmallett return ipd_port - 16; 397210284Sjmallett else 398210284Sjmallett return -1; 399215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_A: 400215990Sjmallett if (ipd_port == 0) 401215990Sjmallett return 0; 402215990Sjmallett else 403215990Sjmallett return -1; 404215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_U: 405215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_G: 406215990Sjmallett if (ipd_port == 0) 407215990Sjmallett return 0x1c; 408215990Sjmallett else 409215990Sjmallett return -1; 410210284Sjmallett case CVMX_BOARD_TYPE_KODAMA: 411210284Sjmallett case CVMX_BOARD_TYPE_EBH3100: 412210284Sjmallett case CVMX_BOARD_TYPE_HIKARI: 413210284Sjmallett case CVMX_BOARD_TYPE_CN3010_EVB_HS5: 414210284Sjmallett case CVMX_BOARD_TYPE_CN3005_EVB_HS5: 415250428Simp#if !defined(OCTEON_VENDOR_GEFES) 416210284Sjmallett case CVMX_BOARD_TYPE_CN3020_EVB_HS5: 417250428Simp#endif 418210284Sjmallett /* Port 0 is WAN connected to a PHY, Port 1 is GMII connected to a 419210284Sjmallett switch */ 420210284Sjmallett if (ipd_port == 0) 421210284Sjmallett return 4; 422210284Sjmallett else if (ipd_port == 1) 423210284Sjmallett return 9; 424210284Sjmallett else 425210284Sjmallett return -1; 426210284Sjmallett case CVMX_BOARD_TYPE_EBH3000: 427210284Sjmallett /* Board has dual SPI4 and no PHYs */ 428210284Sjmallett return -1; 429215990Sjmallett case CVMX_BOARD_TYPE_EBT5810: 430215990Sjmallett /* Board has 10g PHYs hooked up to the MII controller on the 431215990Sjmallett ** IXF18201 MAC. The 10G PHYS use clause 45 MDIO which the CN58XX 432215990Sjmallett ** does not support. All MII accesses go through the IXF part. */ 433215990Sjmallett return -1; 434210284Sjmallett case CVMX_BOARD_TYPE_EBH5200: 435210284Sjmallett case CVMX_BOARD_TYPE_EBH5201: 436210284Sjmallett case CVMX_BOARD_TYPE_EBT5200: 437215990Sjmallett /* Board has 2 management ports */ 438215990Sjmallett if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2))) 439215990Sjmallett return ipd_port - CVMX_HELPER_BOARD_MGMT_IPD_PORT; 440210284Sjmallett /* Board has 4 SGMII ports. The PHYs start right after the MII 441210284Sjmallett ports MII0 = 0, MII1 = 1, SGMII = 2-5 */ 442210284Sjmallett if ((ipd_port >= 0) && (ipd_port < 4)) 443210284Sjmallett return ipd_port+2; 444210284Sjmallett else 445210284Sjmallett return -1; 446210284Sjmallett case CVMX_BOARD_TYPE_EBH5600: 447210284Sjmallett case CVMX_BOARD_TYPE_EBH5601: 448215990Sjmallett case CVMX_BOARD_TYPE_EBH5610: 449215990Sjmallett /* Board has 1 management port */ 450215990Sjmallett if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT) 451215990Sjmallett return 0; 452210284Sjmallett /* Board has 8 SGMII ports. 4 connect out, two connect to a switch, 453210284Sjmallett and 2 loop to each other */ 454210284Sjmallett if ((ipd_port >= 0) && (ipd_port < 4)) 455210284Sjmallett return ipd_port+1; 456210284Sjmallett else 457210284Sjmallett return -1; 458242423Sjmallett case CVMX_BOARD_TYPE_EBT5600: 459242423Sjmallett /* Board has 1 management port */ 460242423Sjmallett if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT) 461242423Sjmallett return 0; 462242423Sjmallett /* Board has 1 XAUI port connected to a switch. */ 463242423Sjmallett return -1; 464215990Sjmallett case CVMX_BOARD_TYPE_EBB5600: 465215990Sjmallett { 466215990Sjmallett static unsigned char qlm_switch_addr = 0; 467215990Sjmallett 468215990Sjmallett /* Board has 1 management port */ 469215990Sjmallett if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT) 470215990Sjmallett return 0; 471215990Sjmallett 472215990Sjmallett /* Board has 8 SGMII ports. 4 connected QLM1, 4 connected QLM3 */ 473215990Sjmallett if ((ipd_port >= 0) && (ipd_port < 4)) 474215990Sjmallett { 475215990Sjmallett if (qlm_switch_addr != 0x3) 476215990Sjmallett { 477215990Sjmallett qlm_switch_addr = 0x3; /* QLM1 */ 478215990Sjmallett cvmx_twsix_write_ia(0, 0x71, 0, 1, 1, qlm_switch_addr); 479215990Sjmallett cvmx_wait_usec(11000); /* Let the write complete */ 480215990Sjmallett } 481215990Sjmallett return ipd_port+1 + (1<<8); 482215990Sjmallett } 483215990Sjmallett else if ((ipd_port >= 16) && (ipd_port < 20)) 484215990Sjmallett { 485215990Sjmallett if (qlm_switch_addr != 0xC) 486215990Sjmallett { 487215990Sjmallett qlm_switch_addr = 0xC; /* QLM3 */ 488215990Sjmallett cvmx_twsix_write_ia(0, 0x71, 0, 1, 1, qlm_switch_addr); 489215990Sjmallett cvmx_wait_usec(11000); /* Let the write complete */ 490215990Sjmallett } 491215990Sjmallett return ipd_port-16+1 + (1<<8); 492215990Sjmallett } 493215990Sjmallett else 494215990Sjmallett return -1; 495215990Sjmallett } 496215990Sjmallett case CVMX_BOARD_TYPE_EBB6300: 497215990Sjmallett /* Board has 2 management ports */ 498215990Sjmallett if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2))) 499215990Sjmallett return ipd_port - CVMX_HELPER_BOARD_MGMT_IPD_PORT + 4; 500215990Sjmallett if ((ipd_port >= 0) && (ipd_port < 4)) 501215990Sjmallett return ipd_port + 1 + (1<<8); 502215990Sjmallett else 503215990Sjmallett return -1; 504232812Sjmallett case CVMX_BOARD_TYPE_EBB6800: 505232812Sjmallett /* Board has 1 management ports */ 506232812Sjmallett if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT) 507232812Sjmallett return 6; 508232812Sjmallett if (ipd_port >= 0x800 && ipd_port < 0x900) /* QLM 0*/ 509232812Sjmallett return 0x101 + ((ipd_port >> 4) & 3); /* SMI 1*/ 510232812Sjmallett if (ipd_port >= 0xa00 && ipd_port < 0xb00) /* QLM 2*/ 511232812Sjmallett return 0x201 + ((ipd_port >> 4) & 3); /* SMI 2*/ 512232812Sjmallett if (ipd_port >= 0xb00 && ipd_port < 0xc00) /* QLM 3*/ 513232812Sjmallett return 0x301 + ((ipd_port >> 4) & 3); /* SMI 3*/ 514232812Sjmallett if (ipd_port >= 0xc00 && ipd_port < 0xd00) /* QLM 4*/ 515232812Sjmallett return 0x001 + ((ipd_port >> 4) & 3); /* SMI 0*/ 516232812Sjmallett return -1; 517232812Sjmallett case CVMX_BOARD_TYPE_EP6300C: 518232812Sjmallett if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT) 519232812Sjmallett return 0x01; 520232812Sjmallett if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT+1) 521232812Sjmallett return 0x02; 522232812Sjmallett#ifdef CVMX_ENABLE_PKO_FUNCTIONS 523232812Sjmallett { 524232812Sjmallett int interface = cvmx_helper_get_interface_num(ipd_port); 525232812Sjmallett int mode = cvmx_helper_interface_get_mode(interface); 526232812Sjmallett if (mode == CVMX_HELPER_INTERFACE_MODE_XAUI) 527232812Sjmallett return ipd_port; 528232812Sjmallett else if ((ipd_port >= 0) && (ipd_port < 4)) 529232812Sjmallett return ipd_port + 3; 530232812Sjmallett else 531232812Sjmallett return -1; 532232812Sjmallett } 533232812Sjmallett#endif 534232812Sjmallett break; 535210284Sjmallett case CVMX_BOARD_TYPE_CUST_NB5: 536210284Sjmallett if (ipd_port == 2) 537210284Sjmallett return 4; 538210284Sjmallett else 539210284Sjmallett return -1; 540210284Sjmallett case CVMX_BOARD_TYPE_NIC_XLE_4G: 541210284Sjmallett /* Board has 4 SGMII ports. connected QLM3(interface 1) */ 542210284Sjmallett if ((ipd_port >= 16) && (ipd_port < 20)) 543210284Sjmallett return ipd_port - 16 + 1; 544210284Sjmallett else 545210284Sjmallett return -1; 546215990Sjmallett case CVMX_BOARD_TYPE_NIC_XLE_10G: 547232812Sjmallett case CVMX_BOARD_TYPE_NIC10E: 548215990Sjmallett return -1; /* We don't use clause 45 MDIO for anything */ 549232812Sjmallett case CVMX_BOARD_TYPE_NIC4E: 550232812Sjmallett if (ipd_port >= 0 && ipd_port <= 3) 551232812Sjmallett return (ipd_port + 0x1f) & 0x1f; 552232812Sjmallett else 553232812Sjmallett return -1; 554232812Sjmallett case CVMX_BOARD_TYPE_NIC2E: 555232812Sjmallett if (ipd_port >= 0 && ipd_port <= 1) 556232812Sjmallett return (ipd_port + 1); 557232812Sjmallett else 558232812Sjmallett return -1; 559232812Sjmallett case CVMX_BOARD_TYPE_REDWING: 560232812Sjmallett return -1; /* No PHYs connected to Octeon */ 561210284Sjmallett case CVMX_BOARD_TYPE_BBGW_REF: 562210284Sjmallett return -1; /* No PHYs are connected to Octeon, everything is through switch */ 563215990Sjmallett case CVMX_BOARD_TYPE_CUST_WSX16: 564215990Sjmallett if (ipd_port >= 0 && ipd_port <= 3) 565215990Sjmallett return ipd_port; 566215990Sjmallett else if (ipd_port >= 16 && ipd_port <= 19) 567215990Sjmallett return ipd_port - 16 + 4; 568215990Sjmallett else 569215990Sjmallett return -1; 570210311Sjmallett 571210311Sjmallett /* Private vendor-defined boards. */ 572210311Sjmallett#if defined(OCTEON_VENDOR_LANNER) 573215014Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR955: 574215014Sjmallett /* Interface 1 is 12 BCM5482S PHYs. */ 575215014Sjmallett if ((ipd_port >= 16) && (ipd_port < 28)) 576215014Sjmallett return ipd_port - 16; 577215014Sjmallett return -1; 578215014Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR730: 579217214Sjmallett if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2))) 580217214Sjmallett return (ipd_port - CVMX_HELPER_BOARD_MGMT_IPD_PORT) + 0x81; 581215014Sjmallett if ((ipd_port >= 0) && (ipd_port < 4)) 582215014Sjmallett return ipd_port; 583215014Sjmallett return -1; 584210311Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR320: 585216476Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR321X: 586213346Sjmallett /* Port 0 is a Marvell 88E6161 switch, ports 1 and 2 are Marvell 587213346Sjmallett 88E1111 interfaces. */ 588210311Sjmallett switch (ipd_port) { 589210311Sjmallett case 0: 590213346Sjmallett return 16; 591210311Sjmallett case 1: 592210311Sjmallett return 1; 593210311Sjmallett case 2: 594210311Sjmallett return 2; 595210311Sjmallett default: 596210311Sjmallett return -1; 597210311Sjmallett } 598210311Sjmallett#endif 599244984Sjmallett#if defined(OCTEON_VENDOR_UBIQUITI) 600244984Sjmallett case CVMX_BOARD_TYPE_CUST_UBIQUITI_E100: 601244984Sjmallett if (ipd_port > 2) 602244984Sjmallett return -1; 603244984Sjmallett return (7 - ipd_port); 604244984Sjmallett#endif 605242116Sjmallett#if defined(OCTEON_VENDOR_RADISYS) 606242116Sjmallett case CVMX_BOARD_TYPE_CUST_RADISYS_RSYS4GBE: 607242116Sjmallett /* No MII. */ 608242116Sjmallett return -1; 609242116Sjmallett#endif 610250428Simp#if defined(OCTEON_VENDOR_GEFES) 611250428Simp case CVMX_BOARD_TYPE_AT5810: 612250428Simp return -1; 613250428Simp case CVMX_BOARD_TYPE_TNPA3804: 614250428Simp case CVMX_BOARD_TYPE_CUST_TNPA5804: 615250428Simp case CVMX_BOARD_TYPE_CUST_W5800: 616250428Simp case CVMX_BOARD_TYPE_WNPA3850: 617250428Simp case CVMX_BOARD_TYPE_W3860: 618250428Simp return -1;// RGMII boards should use inbad status 619250428Simp case CVMX_BOARD_TYPE_CUST_W5651X: 620250428Simp case CVMX_BOARD_TYPE_CUST_W5650: 621250428Simp case CVMX_BOARD_TYPE_CUST_TNPA56X4: 622250428Simp case CVMX_BOARD_TYPE_CUST_TNPA5651X: 623250428Simp case CVMX_BOARD_TYPE_CUST_W63XX: 624250428Simp return -1; /* No PHYs are connected to Octeon, PHYs inside of SFPs which is accessed over TWSI */ 625250428Simp case CVMX_BOARD_TYPE_CUST_W5434: 626250428Simp /* Board has 4 SGMII ports. 4 connect out 627250428Simp * must return the MII address of the PHY connected to each IPD port 628250428Simp */ 629250428Simp if ((ipd_port >= 16) && (ipd_port < 20)) 630250428Simp return ipd_port - 16 + 0x40; 631250428Simp else 632250428Simp return -1; 633250428Simp#endif 634210284Sjmallett } 635210284Sjmallett 636210284Sjmallett /* Some unknown board. Somebody forgot to update this function... */ 637215990Sjmallett cvmx_dprintf("%s: Unknown board type %d\n", 638215990Sjmallett __FUNCTION__, cvmx_sysinfo_get()->board_type); 639210284Sjmallett return -1; 640210284Sjmallett} 641215990Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 642215990SjmallettEXPORT_SYMBOL(cvmx_helper_board_get_mii_address); 643215990Sjmallett#endif 644210284Sjmallett 645232812Sjmallett/** 646232812Sjmallett * @INTERNAL 647232812Sjmallett * Get link state of marvell PHY 648232812Sjmallett */ 649232812Sjmallettstatic cvmx_helper_link_info_t __get_marvell_phy_link_state(int phy_addr) 650232812Sjmallett{ 651232812Sjmallett cvmx_helper_link_info_t result; 652232812Sjmallett int phy_status; 653210284Sjmallett 654232812Sjmallett result.u64 = 0; 655232812Sjmallett /*All the speed information can be read from register 17 in one go.*/ 656232812Sjmallett phy_status = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 17); 657232812Sjmallett 658232812Sjmallett /* If the resolve bit 11 isn't set, see if autoneg is turned off 659232812Sjmallett (bit 12, reg 0). The resolve bit doesn't get set properly when 660232812Sjmallett autoneg is off, so force it */ 661232812Sjmallett if ((phy_status & (1<<11)) == 0) 662232812Sjmallett { 663232812Sjmallett int auto_status = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 0); 664232812Sjmallett if ((auto_status & (1<<12)) == 0) 665232812Sjmallett phy_status |= 1<<11; 666232812Sjmallett } 667232812Sjmallett 668232812Sjmallett /* Only return a link if the PHY has finished auto negotiation 669232812Sjmallett and set the resolved bit (bit 11) */ 670232812Sjmallett if (phy_status & (1<<11)) 671232812Sjmallett { 672232812Sjmallett result.s.link_up = 1; 673232812Sjmallett result.s.full_duplex = ((phy_status>>13)&1); 674232812Sjmallett switch ((phy_status>>14)&3) 675232812Sjmallett { 676232812Sjmallett case 0: /* 10 Mbps */ 677232812Sjmallett result.s.speed = 10; 678232812Sjmallett break; 679232812Sjmallett case 1: /* 100 Mbps */ 680232812Sjmallett result.s.speed = 100; 681232812Sjmallett break; 682232812Sjmallett case 2: /* 1 Gbps */ 683232812Sjmallett result.s.speed = 1000; 684232812Sjmallett break; 685232812Sjmallett case 3: /* Illegal */ 686232812Sjmallett result.u64 = 0; 687232812Sjmallett break; 688232812Sjmallett } 689232812Sjmallett } 690232812Sjmallett return result; 691232812Sjmallett} 692232812Sjmallett 693210284Sjmallett/** 694210284Sjmallett * @INTERNAL 695232812Sjmallett * Get link state of broadcom PHY 696232812Sjmallett */ 697232812Sjmallettstatic cvmx_helper_link_info_t __get_broadcom_phy_link_state(int phy_addr) 698232812Sjmallett{ 699232812Sjmallett cvmx_helper_link_info_t result; 700232812Sjmallett int phy_status; 701232812Sjmallett 702232812Sjmallett result.u64 = 0; 703232812Sjmallett /* Below we are going to read SMI/MDIO register 0x19 which works 704232812Sjmallett on Broadcom parts */ 705232812Sjmallett phy_status = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 0x19); 706232812Sjmallett switch ((phy_status>>8) & 0x7) 707232812Sjmallett { 708232812Sjmallett case 0: 709232812Sjmallett result.u64 = 0; 710232812Sjmallett break; 711232812Sjmallett case 1: 712232812Sjmallett result.s.link_up = 1; 713232812Sjmallett result.s.full_duplex = 0; 714232812Sjmallett result.s.speed = 10; 715232812Sjmallett break; 716232812Sjmallett case 2: 717232812Sjmallett result.s.link_up = 1; 718232812Sjmallett result.s.full_duplex = 1; 719232812Sjmallett result.s.speed = 10; 720232812Sjmallett break; 721232812Sjmallett case 3: 722232812Sjmallett result.s.link_up = 1; 723232812Sjmallett result.s.full_duplex = 0; 724232812Sjmallett result.s.speed = 100; 725232812Sjmallett break; 726232812Sjmallett case 4: 727232812Sjmallett result.s.link_up = 1; 728232812Sjmallett result.s.full_duplex = 1; 729232812Sjmallett result.s.speed = 100; 730232812Sjmallett break; 731232812Sjmallett case 5: 732232812Sjmallett result.s.link_up = 1; 733232812Sjmallett result.s.full_duplex = 1; 734232812Sjmallett result.s.speed = 100; 735232812Sjmallett break; 736232812Sjmallett case 6: 737232812Sjmallett result.s.link_up = 1; 738232812Sjmallett result.s.full_duplex = 0; 739232812Sjmallett result.s.speed = 1000; 740232812Sjmallett break; 741232812Sjmallett case 7: 742232812Sjmallett result.s.link_up = 1; 743232812Sjmallett result.s.full_duplex = 1; 744232812Sjmallett result.s.speed = 1000; 745232812Sjmallett break; 746232812Sjmallett } 747232812Sjmallett return result; 748232812Sjmallett} 749232812Sjmallett 750232812Sjmallett 751232812Sjmallett/** 752232812Sjmallett * @INTERNAL 753232812Sjmallett * Get link state using inband status 754232812Sjmallett */ 755232812Sjmallettstatic cvmx_helper_link_info_t __get_inband_link_state(int ipd_port) 756232812Sjmallett{ 757232812Sjmallett cvmx_helper_link_info_t result; 758232812Sjmallett cvmx_gmxx_rxx_rx_inbnd_t inband_status; 759232812Sjmallett int interface = cvmx_helper_get_interface_num(ipd_port); 760232812Sjmallett int index = cvmx_helper_get_interface_index_num(ipd_port); 761232812Sjmallett 762232812Sjmallett result.u64 = 0; 763232812Sjmallett inband_status.u64 = cvmx_read_csr(CVMX_GMXX_RXX_RX_INBND(index, interface)); 764232812Sjmallett result.s.link_up = inband_status.s.status; 765232812Sjmallett result.s.full_duplex = inband_status.s.duplex; 766232812Sjmallett switch (inband_status.s.speed) 767232812Sjmallett { 768232812Sjmallett case 0: /* 10 Mbps */ 769232812Sjmallett result.s.speed = 10; 770232812Sjmallett break; 771232812Sjmallett case 1: /* 100 Mbps */ 772232812Sjmallett result.s.speed = 100; 773232812Sjmallett break; 774232812Sjmallett case 2: /* 1 Gbps */ 775232812Sjmallett result.s.speed = 1000; 776232812Sjmallett break; 777232812Sjmallett case 3: /* Illegal */ 778232812Sjmallett result.u64 = 0; 779232812Sjmallett break; 780232812Sjmallett } 781232812Sjmallett return result; 782232812Sjmallett} 783232812Sjmallett 784232812Sjmallett#if !defined(CVMX_BUILD_FOR_LINUX_KERNEL) && (!defined(__FreeBSD__) || !defined(_KERNEL)) 785232812Sjmallett/** 786232812Sjmallett * @INTERNAL 787232812Sjmallett * Switch MDIO mux to the specified port. 788232812Sjmallett */ 789232812Sjmallettstatic int __switch_mdio_mux(int ipd_port) 790232812Sjmallett{ 791232812Sjmallett /* This method is board specific and doesn't use the device tree 792232812Sjmallett information as SE doesn't implement MDIO MUX abstration */ 793232812Sjmallett switch (cvmx_sysinfo_get()->board_type) 794232812Sjmallett { 795232812Sjmallett case CVMX_BOARD_TYPE_EBB5600: 796232812Sjmallett { 797232812Sjmallett static unsigned char qlm_switch_addr = 0; 798232812Sjmallett /* Board has 1 management port */ 799232812Sjmallett if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT) 800232812Sjmallett return 0; 801232812Sjmallett /* Board has 8 SGMII ports. 4 connected QLM1, 4 connected QLM3 */ 802232812Sjmallett if ((ipd_port >= 0) && (ipd_port < 4)) 803232812Sjmallett { 804232812Sjmallett if (qlm_switch_addr != 0x3) 805232812Sjmallett { 806232812Sjmallett qlm_switch_addr = 0x3; /* QLM1 */ 807232812Sjmallett cvmx_twsix_write_ia(0, 0x71, 0, 1, 1, qlm_switch_addr); 808232812Sjmallett cvmx_wait_usec(11000); /* Let the write complete */ 809232812Sjmallett } 810232812Sjmallett return ipd_port+1 + (1<<8); 811232812Sjmallett } 812232812Sjmallett else if ((ipd_port >= 16) && (ipd_port < 20)) 813232812Sjmallett { 814232812Sjmallett if (qlm_switch_addr != 0xC) 815232812Sjmallett { 816232812Sjmallett qlm_switch_addr = 0xC; /* QLM3 */ 817232812Sjmallett cvmx_twsix_write_ia(0, 0x71, 0, 1, 1, qlm_switch_addr); 818232812Sjmallett cvmx_wait_usec(11000); /* Let the write complete */ 819232812Sjmallett } 820232812Sjmallett return ipd_port-16+1 + (1<<8); 821232812Sjmallett } 822232812Sjmallett else 823232812Sjmallett return -1; 824232812Sjmallett } 825232812Sjmallett case CVMX_BOARD_TYPE_EBB6600: 826232812Sjmallett { 827232812Sjmallett static unsigned char qlm_switch_addr = 0; 828232812Sjmallett int old_twsi_switch_reg; 829232812Sjmallett /* Board has 2 management ports */ 830232812Sjmallett if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && 831232812Sjmallett (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2))) 832232812Sjmallett return ipd_port - CVMX_HELPER_BOARD_MGMT_IPD_PORT + 4; 833232812Sjmallett if ((ipd_port >= 0) && (ipd_port < 4)) /* QLM 2 */ 834232812Sjmallett { 835232812Sjmallett if (qlm_switch_addr != 2) 836232812Sjmallett { 837232812Sjmallett int tries; 838232812Sjmallett qlm_switch_addr = 2; 839232812Sjmallett tries = 3; 840232812Sjmallett do { 841232812Sjmallett old_twsi_switch_reg = cvmx_twsix_read8(0, 0x70, 0); 842232812Sjmallett } while (tries-- > 0 && old_twsi_switch_reg < 0); 843232812Sjmallett /* Set I2C MUX to enable port expander */ 844232812Sjmallett cvmx_retry_i2c_write(0, 0x70, 0, 1, 0, 8); 845232812Sjmallett /* Set selecter to QLM 1 */ 846232812Sjmallett cvmx_retry_i2c_write(0, 0x38, 0, 1, 0, 0xff); 847232812Sjmallett /* disable port expander */ 848232812Sjmallett cvmx_retry_i2c_write(0, 0x70, 0, 1, 0, old_twsi_switch_reg); 849232812Sjmallett } 850232812Sjmallett return 0x101 + ipd_port; 851232812Sjmallett } 852232812Sjmallett else if ((ipd_port >= 16) && (ipd_port < 20)) /* QLM 1 */ 853232812Sjmallett { 854232812Sjmallett if (qlm_switch_addr != 1) 855232812Sjmallett { 856232812Sjmallett int tries; 857232812Sjmallett qlm_switch_addr = 1; 858232812Sjmallett tries = 3; 859232812Sjmallett do { 860232812Sjmallett old_twsi_switch_reg = cvmx_twsix_read8(0, 0x70, 0); 861232812Sjmallett } while (tries-- > 0 && old_twsi_switch_reg < 0); 862232812Sjmallett /* Set I2C MUX to enable port expander */ 863232812Sjmallett cvmx_retry_i2c_write(0, 0x70, 0, 1, 0, 8); 864232812Sjmallett /* Set selecter to QLM 2 */ 865232812Sjmallett cvmx_retry_i2c_write(0, 0x38, 0, 1, 0, 0xf7); 866232812Sjmallett /* disable port expander */ 867232812Sjmallett cvmx_retry_i2c_write(0, 0x70, 0, 1, 0, old_twsi_switch_reg); 868232812Sjmallett } 869232812Sjmallett return 0x101 + (ipd_port - 16); 870232812Sjmallett } else 871232812Sjmallett return -1; 872232812Sjmallett } 873232812Sjmallett case CVMX_BOARD_TYPE_EBB6100: 874232812Sjmallett { 875232812Sjmallett static char gpio_configured = 0; 876232812Sjmallett 877232812Sjmallett if (!gpio_configured) 878232812Sjmallett { 879232812Sjmallett cvmx_gpio_cfg(3, 1); 880232812Sjmallett gpio_configured = 1; 881232812Sjmallett } 882232812Sjmallett /* Board has 2 management ports */ 883232812Sjmallett if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && 884232812Sjmallett (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2))) 885232812Sjmallett return ipd_port - CVMX_HELPER_BOARD_MGMT_IPD_PORT + 4; 886232812Sjmallett if ((ipd_port >= 0) && (ipd_port < 4)) /* QLM 2 */ 887232812Sjmallett { 888232812Sjmallett cvmx_gpio_set(1ull << 3); 889232812Sjmallett return 0x101 + ipd_port; 890232812Sjmallett } 891232812Sjmallett else if ((ipd_port >= 16) && (ipd_port < 20)) /* QLM 0 */ 892232812Sjmallett { 893232812Sjmallett cvmx_gpio_clear(1ull << 3); 894232812Sjmallett return 0x101 + (ipd_port - 16); 895232812Sjmallett } 896232812Sjmallett else 897232812Sjmallett { 898232812Sjmallett printf("%s: Unknown ipd port 0x%x\n", __func__, ipd_port); 899232812Sjmallett return -1; 900232812Sjmallett } 901232812Sjmallett } 902232812Sjmallett default: 903232812Sjmallett { 904232812Sjmallett cvmx_dprintf("ERROR : unexpected mdio switch for board=%08x\n", 905232812Sjmallett cvmx_sysinfo_get()->board_type); 906232812Sjmallett return -1; 907232812Sjmallett } 908232812Sjmallett } 909232812Sjmallett /* should never get here */ 910232812Sjmallett return -1; 911232812Sjmallett} 912232812Sjmallett 913232812Sjmallett/** 914232812Sjmallett * @INTERNAL 915232812Sjmallett * This function is used ethernet ports link speed. This functions uses the 916232812Sjmallett * device tree information to determine the phy address and type of PHY. 917232812Sjmallett * The only supproted PHYs are Marvell and Broadcom. 918232812Sjmallett * 919232812Sjmallett * @param ipd_port IPD input port associated with the port we want to get link 920232812Sjmallett * status for. 921232812Sjmallett * 922232812Sjmallett * @return The ports link status. If the link isn't fully resolved, this must 923232812Sjmallett * return zero. 924232812Sjmallett */ 925232812Sjmallett 926232812Sjmallettcvmx_helper_link_info_t __cvmx_helper_board_link_get_from_dt(int ipd_port) 927232812Sjmallett{ 928232812Sjmallett cvmx_helper_link_info_t result; 929232812Sjmallett cvmx_phy_info_t phy_info; 930232812Sjmallett 931232812Sjmallett result.u64 = 0; 932232812Sjmallett if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) 933232812Sjmallett { 934232812Sjmallett /* The simulator gives you a simulated 1Gbps full duplex link */ 935232812Sjmallett result.s.link_up = 1; 936232812Sjmallett result.s.full_duplex = 1; 937232812Sjmallett result.s.speed = 1000; 938232812Sjmallett return result; 939232812Sjmallett } 940232812Sjmallett phy_info = __get_phy_info_from_dt(ipd_port); 941232812Sjmallett //cvmx_dprintf("ipd_port=%d phy_addr=%d dc=%d type=%d \n", ipd_port, 942232812Sjmallett // phy_info.phy_addr, phy_info.direct_connect, phy_info.phy_type); 943232812Sjmallett if (phy_info.phy_addr < 0) return result; 944232812Sjmallett 945232812Sjmallett if (phy_info.direct_connect == 0) 946232812Sjmallett __switch_mdio_mux(ipd_port); 947232812Sjmallett switch(phy_info.phy_type) 948232812Sjmallett { 949232812Sjmallett case BROADCOM_GENERIC_PHY: 950232812Sjmallett result = __get_broadcom_phy_link_state(phy_info.phy_addr); 951232812Sjmallett break; 952232812Sjmallett case MARVELL_GENERIC_PHY: 953232812Sjmallett result = __get_marvell_phy_link_state(phy_info.phy_addr); 954232812Sjmallett break; 955232812Sjmallett default: 956232812Sjmallett result = __get_inband_link_state(ipd_port); 957232812Sjmallett } 958232812Sjmallett return result; 959232812Sjmallett 960232812Sjmallett} 961232812Sjmallett#endif 962232812Sjmallett 963232812Sjmallett/** 964232812Sjmallett * @INTERNAL 965232812Sjmallett * This function invokes __cvmx_helper_board_link_get_from_dt when device tree 966232812Sjmallett * info is available. When the device tree information is not available then 967232812Sjmallett * this function is the board specific method of determining an 968210284Sjmallett * ethernet ports link speed. Most Octeon boards have Marvell PHYs 969210284Sjmallett * and are handled by the fall through case. This function must be 970210284Sjmallett * updated for boards that don't have the normal Marvell PHYs. 971210284Sjmallett * 972210284Sjmallett * This function must be modified for every new Octeon board. 973210284Sjmallett * Internally it uses switch statements based on the cvmx_sysinfo 974210284Sjmallett * data to determine board types and revisions. It relies on the 975210284Sjmallett * fact that every Octeon board receives a unique board type 976210284Sjmallett * enumeration from the bootloader. 977210284Sjmallett * 978210284Sjmallett * @param ipd_port IPD input port associated with the port we want to get link 979210284Sjmallett * status for. 980210284Sjmallett * 981210284Sjmallett * @return The ports link status. If the link isn't fully resolved, this must 982210284Sjmallett * return zero. 983210284Sjmallett */ 984210284Sjmallettcvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port) 985210284Sjmallett{ 986210284Sjmallett cvmx_helper_link_info_t result; 987210284Sjmallett int phy_addr; 988210284Sjmallett int is_broadcom_phy = 0; 989210284Sjmallett 990232812Sjmallett#if !defined(CVMX_BUILD_FOR_LINUX_KERNEL) && (!defined(__FreeBSD__) || !defined(_KERNEL)) 991232812Sjmallett if (cvmx_sysinfo_get()->fdt_addr) 992232812Sjmallett { 993232812Sjmallett return __cvmx_helper_board_link_get_from_dt(ipd_port); 994232812Sjmallett } 995232812Sjmallett#endif 996232812Sjmallett 997210284Sjmallett /* Give the user a chance to override the processing of this function */ 998210284Sjmallett if (cvmx_override_board_link_get) 999210284Sjmallett return cvmx_override_board_link_get(ipd_port); 1000210284Sjmallett 1001210284Sjmallett /* Unless we fix it later, all links are defaulted to down */ 1002210284Sjmallett result.u64 = 0; 1003210284Sjmallett 1004210311Sjmallett#if !defined(OCTEON_BOARD_CAPK_0100ND) 1005210284Sjmallett /* This switch statement should handle all ports that either don't use 1006210284Sjmallett Marvell PHYS, or don't support in-band status */ 1007210284Sjmallett switch (cvmx_sysinfo_get()->board_type) 1008210284Sjmallett { 1009210284Sjmallett case CVMX_BOARD_TYPE_SIM: 1010210284Sjmallett /* The simulator gives you a simulated 1Gbps full duplex link */ 1011210284Sjmallett result.s.link_up = 1; 1012210284Sjmallett result.s.full_duplex = 1; 1013210284Sjmallett result.s.speed = 1000; 1014210284Sjmallett return result; 1015215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_A: 1016215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_U: 1017215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_G: 1018215990Sjmallett break; 1019210284Sjmallett case CVMX_BOARD_TYPE_EBH3100: 1020210284Sjmallett case CVMX_BOARD_TYPE_CN3010_EVB_HS5: 1021210284Sjmallett case CVMX_BOARD_TYPE_CN3005_EVB_HS5: 1022250428Simp#if !defined(OCTEON_VENDOR_GEFES) 1023210284Sjmallett case CVMX_BOARD_TYPE_CN3020_EVB_HS5: 1024250428Simp#endif 1025210284Sjmallett /* Port 1 on these boards is always Gigabit */ 1026210284Sjmallett if (ipd_port == 1) 1027210284Sjmallett { 1028210284Sjmallett result.s.link_up = 1; 1029210284Sjmallett result.s.full_duplex = 1; 1030210284Sjmallett result.s.speed = 1000; 1031210284Sjmallett return result; 1032210284Sjmallett } 1033210284Sjmallett /* Fall through to the generic code below */ 1034210284Sjmallett break; 1035242423Sjmallett case CVMX_BOARD_TYPE_EBT5600: 1036215990Sjmallett case CVMX_BOARD_TYPE_EBH5600: 1037215990Sjmallett case CVMX_BOARD_TYPE_EBH5601: 1038215990Sjmallett case CVMX_BOARD_TYPE_EBH5610: 1039215990Sjmallett /* Board has 1 management ports */ 1040215990Sjmallett if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT) 1041215990Sjmallett is_broadcom_phy = 1; 1042215990Sjmallett break; 1043215990Sjmallett case CVMX_BOARD_TYPE_EBH5200: 1044215990Sjmallett case CVMX_BOARD_TYPE_EBH5201: 1045215990Sjmallett case CVMX_BOARD_TYPE_EBT5200: 1046215990Sjmallett /* Board has 2 management ports */ 1047215990Sjmallett if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2))) 1048215990Sjmallett is_broadcom_phy = 1; 1049215990Sjmallett break; 1050232812Sjmallett case CVMX_BOARD_TYPE_EBB6100: 1051215990Sjmallett case CVMX_BOARD_TYPE_EBB6300: /* Only for MII mode, with PHY addresses 0/1. Default is RGMII*/ 1052232812Sjmallett case CVMX_BOARD_TYPE_EBB6600: /* Only for MII mode, with PHY addresses 0/1. Default is RGMII*/ 1053215990Sjmallett if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2)) 1054215990Sjmallett && cvmx_helper_board_get_mii_address(ipd_port) >= 0 && cvmx_helper_board_get_mii_address(ipd_port) <= 1) 1055215990Sjmallett is_broadcom_phy = 1; 1056215990Sjmallett break; 1057232812Sjmallett case CVMX_BOARD_TYPE_EP6300C: 1058232812Sjmallett is_broadcom_phy = 1; 1059232812Sjmallett break; 1060210284Sjmallett case CVMX_BOARD_TYPE_CUST_NB5: 1061210284Sjmallett /* Port 1 on these boards is always Gigabit */ 1062210284Sjmallett if (ipd_port == 1) 1063210284Sjmallett { 1064210284Sjmallett result.s.link_up = 1; 1065210284Sjmallett result.s.full_duplex = 1; 1066210284Sjmallett result.s.speed = 1000; 1067210284Sjmallett return result; 1068210284Sjmallett } 1069210284Sjmallett else /* The other port uses a broadcom PHY */ 1070210284Sjmallett is_broadcom_phy = 1; 1071210284Sjmallett break; 1072210284Sjmallett case CVMX_BOARD_TYPE_BBGW_REF: 1073210284Sjmallett /* Port 1 on these boards is always Gigabit */ 1074210284Sjmallett if (ipd_port == 2) 1075215990Sjmallett { 1076210284Sjmallett /* Port 2 is not hooked up */ 1077210284Sjmallett result.u64 = 0; 1078210284Sjmallett return result; 1079210284Sjmallett } 1080210284Sjmallett else 1081210284Sjmallett { 1082210284Sjmallett /* Ports 0 and 1 connect to the switch */ 1083210284Sjmallett result.s.link_up = 1; 1084210284Sjmallett result.s.full_duplex = 1; 1085210284Sjmallett result.s.speed = 1000; 1086210284Sjmallett return result; 1087210284Sjmallett } 1088232812Sjmallett case CVMX_BOARD_TYPE_NIC4E: 1089232812Sjmallett case CVMX_BOARD_TYPE_NIC2E: 1090232812Sjmallett is_broadcom_phy = 1; 1091210284Sjmallett break; 1092210311Sjmallett /* Private vendor-defined boards. */ 1093210311Sjmallett#if defined(OCTEON_VENDOR_LANNER) 1094215014Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR730: 1095215014Sjmallett /* Ports are BCM5482S */ 1096215014Sjmallett is_broadcom_phy = 1; 1097215014Sjmallett break; 1098210311Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR320: 1099216476Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR321X: 1100210311Sjmallett /* Port 0 connects to the switch */ 1101210311Sjmallett if (ipd_port == 0) 1102210311Sjmallett { 1103210311Sjmallett result.s.link_up = 1; 1104210311Sjmallett result.s.full_duplex = 1; 1105210311Sjmallett result.s.speed = 1000; 1106210311Sjmallett return result; 1107210311Sjmallett } 1108210311Sjmallett break; 1109210311Sjmallett#endif 1110250428Simp#if defined(OCTEON_VENDOR_GEFES) 1111250428Simp case CVMX_BOARD_TYPE_CUST_TNPA5651X: 1112250428Simp /* Since we don't auto-negotiate... 1Gbps full duplex link */ 1113250428Simp result.s.link_up = 1; 1114250428Simp result.s.full_duplex = 1; 1115250428Simp result.s.speed = 1000; 1116250428Simp return result; 1117250428Simp break; 1118250428Simp#endif 1119210284Sjmallett } 1120210311Sjmallett#endif 1121210284Sjmallett 1122210284Sjmallett phy_addr = cvmx_helper_board_get_mii_address(ipd_port); 1123232812Sjmallett //cvmx_dprintf("ipd_port=%d phy_addr=%d broadcom=%d\n", 1124232812Sjmallett // ipd_port, phy_addr, is_broadcom_phy); 1125210284Sjmallett if (phy_addr != -1) 1126210284Sjmallett { 1127210284Sjmallett if (is_broadcom_phy) 1128210284Sjmallett { 1129232812Sjmallett result = __get_broadcom_phy_link_state(phy_addr); 1130210284Sjmallett } 1131210284Sjmallett else 1132210284Sjmallett { 1133232812Sjmallett /* This code assumes we are using a Marvell Gigabit PHY. */ 1134232812Sjmallett result = __get_marvell_phy_link_state(phy_addr); 1135210284Sjmallett } 1136210284Sjmallett } 1137232812Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN58XX) 1138232812Sjmallett || OCTEON_IS_MODEL(OCTEON_CN50XX)) 1139210284Sjmallett { 1140210284Sjmallett /* We don't have a PHY address, so attempt to use in-band status. It is 1141210284Sjmallett really important that boards not supporting in-band status never get 1142210284Sjmallett here. Reading broken in-band status tends to do bad things */ 1143232812Sjmallett result = __get_inband_link_state(ipd_port); 1144210284Sjmallett } 1145250428Simp#if defined(OCTEON_VENDOR_GEFES) 1146250428Simp else if( (OCTEON_IS_MODEL(OCTEON_CN56XX)) || (OCTEON_IS_MODEL(OCTEON_CN63XX)) ) 1147250428Simp { 1148250428Simp int interface = cvmx_helper_get_interface_num(ipd_port); 1149250428Simp int index = cvmx_helper_get_interface_index_num(ipd_port); 1150250428Simp cvmx_pcsx_miscx_ctl_reg_t mode_type; 1151250428Simp cvmx_pcsx_mrx_status_reg_t mrx_status; 1152250428Simp cvmx_pcsx_anx_adv_reg_t anxx_adv; 1153250428Simp cvmx_pcsx_sgmx_lp_adv_reg_t sgmii_inband_status; 1154250428Simp 1155250428Simp anxx_adv.u64 = cvmx_read_csr(CVMX_PCSX_ANX_ADV_REG(index, interface)); 1156250428Simp mrx_status.u64 = cvmx_read_csr(CVMX_PCSX_MRX_STATUS_REG(index, interface)); 1157250428Simp 1158250428Simp mode_type.u64 = cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface)); 1159250428Simp 1160250428Simp /* Read Octeon's inband status */ 1161250428Simp sgmii_inband_status.u64 = cvmx_read_csr(CVMX_PCSX_SGMX_LP_ADV_REG(index, interface)); 1162250428Simp 1163250428Simp result.s.link_up = sgmii_inband_status.s.link; 1164250428Simp result.s.full_duplex = sgmii_inband_status.s.dup; 1165250428Simp switch (sgmii_inband_status.s.speed) 1166250428Simp { 1167250428Simp case 0: /* 10 Mbps */ 1168250428Simp result.s.speed = 10; 1169250428Simp break; 1170250428Simp case 1: /* 100 Mbps */ 1171250428Simp result.s.speed = 100; 1172250428Simp break; 1173250428Simp case 2: /* 1 Gbps */ 1174250428Simp result.s.speed = 1000; 1175250428Simp break; 1176250428Simp case 3: /* Illegal */ 1177250428Simp result.s.speed = 0; 1178250428Simp result.s.link_up = 0; 1179250428Simp break; 1180250428Simp } 1181250428Simp } 1182250428Simp#endif 1183210284Sjmallett else 1184210284Sjmallett { 1185210284Sjmallett /* We don't have a PHY address and we don't have in-band status. There 1186210284Sjmallett is no way to determine the link speed. Return down assuming this 1187210284Sjmallett port isn't wired */ 1188210284Sjmallett result.u64 = 0; 1189210284Sjmallett } 1190210284Sjmallett 1191210284Sjmallett /* If link is down, return all fields as zero. */ 1192210284Sjmallett if (!result.s.link_up) 1193210284Sjmallett result.u64 = 0; 1194210284Sjmallett 1195210284Sjmallett return result; 1196210284Sjmallett} 1197210284Sjmallett 1198210284Sjmallett 1199210284Sjmallett/** 1200210284Sjmallett * This function as a board specific method of changing the PHY 1201215990Sjmallett * speed, duplex, and autonegotiation. This programs the PHY and 1202210284Sjmallett * not Octeon. This can be used to force Octeon's links to 1203210284Sjmallett * specific settings. 1204210284Sjmallett * 1205210284Sjmallett * @param phy_addr The address of the PHY to program 1206215990Sjmallett * @param link_flags 1207215990Sjmallett * Flags to control autonegotiation. Bit 0 is autonegotiation 1208215990Sjmallett * enable/disable to maintain backward compatibility. 1209215990Sjmallett * @param link_info Link speed to program. If the speed is zero and autonegotiation 1210210284Sjmallett * is enabled, all possible negotiation speeds are advertised. 1211210284Sjmallett * 1212210284Sjmallett * @return Zero on success, negative on failure 1213210284Sjmallett */ 1214210284Sjmallettint cvmx_helper_board_link_set_phy(int phy_addr, cvmx_helper_board_set_phy_link_flags_types_t link_flags, 1215210284Sjmallett cvmx_helper_link_info_t link_info) 1216210284Sjmallett{ 1217210284Sjmallett 1218210284Sjmallett /* Set the flow control settings based on link_flags */ 1219210284Sjmallett if ((link_flags & set_phy_link_flags_flow_control_mask) != set_phy_link_flags_flow_control_dont_touch) 1220210284Sjmallett { 1221210284Sjmallett cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; 1222210284Sjmallett reg_autoneg_adver.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER); 1223210284Sjmallett reg_autoneg_adver.s.asymmetric_pause = (link_flags & set_phy_link_flags_flow_control_mask) == set_phy_link_flags_flow_control_enable; 1224210284Sjmallett reg_autoneg_adver.s.pause = (link_flags & set_phy_link_flags_flow_control_mask) == set_phy_link_flags_flow_control_enable; 1225210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER, reg_autoneg_adver.u16); 1226210284Sjmallett } 1227210284Sjmallett 1228210284Sjmallett /* If speed isn't set and autoneg is on advertise all supported modes */ 1229210284Sjmallett if ((link_flags & set_phy_link_flags_autoneg) && (link_info.s.speed == 0)) 1230210284Sjmallett { 1231210284Sjmallett cvmx_mdio_phy_reg_control_t reg_control; 1232210284Sjmallett cvmx_mdio_phy_reg_status_t reg_status; 1233210284Sjmallett cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; 1234210284Sjmallett cvmx_mdio_phy_reg_extended_status_t reg_extended_status; 1235210284Sjmallett cvmx_mdio_phy_reg_control_1000_t reg_control_1000; 1236210284Sjmallett 1237210284Sjmallett reg_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_STATUS); 1238210284Sjmallett reg_autoneg_adver.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER); 1239210284Sjmallett reg_autoneg_adver.s.advert_100base_t4 = reg_status.s.capable_100base_t4; 1240210284Sjmallett reg_autoneg_adver.s.advert_10base_tx_full = reg_status.s.capable_10_full; 1241210284Sjmallett reg_autoneg_adver.s.advert_10base_tx_half = reg_status.s.capable_10_half; 1242210284Sjmallett reg_autoneg_adver.s.advert_100base_tx_full = reg_status.s.capable_100base_x_full; 1243210284Sjmallett reg_autoneg_adver.s.advert_100base_tx_half = reg_status.s.capable_100base_x_half; 1244210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER, reg_autoneg_adver.u16); 1245210284Sjmallett if (reg_status.s.capable_extended_status) 1246210284Sjmallett { 1247210284Sjmallett reg_extended_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_EXTENDED_STATUS); 1248210284Sjmallett reg_control_1000.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000); 1249210284Sjmallett reg_control_1000.s.advert_1000base_t_full = reg_extended_status.s.capable_1000base_t_full; 1250210284Sjmallett reg_control_1000.s.advert_1000base_t_half = reg_extended_status.s.capable_1000base_t_half; 1251210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000, reg_control_1000.u16); 1252210284Sjmallett } 1253210284Sjmallett reg_control.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL); 1254210284Sjmallett reg_control.s.autoneg_enable = 1; 1255210284Sjmallett reg_control.s.restart_autoneg = 1; 1256210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); 1257210284Sjmallett } 1258210284Sjmallett else if ((link_flags & set_phy_link_flags_autoneg)) 1259210284Sjmallett { 1260210284Sjmallett cvmx_mdio_phy_reg_control_t reg_control; 1261210284Sjmallett cvmx_mdio_phy_reg_status_t reg_status; 1262210284Sjmallett cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; 1263210284Sjmallett cvmx_mdio_phy_reg_control_1000_t reg_control_1000; 1264210284Sjmallett 1265210284Sjmallett reg_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_STATUS); 1266210284Sjmallett reg_autoneg_adver.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER); 1267210284Sjmallett reg_autoneg_adver.s.advert_100base_t4 = 0; 1268210284Sjmallett reg_autoneg_adver.s.advert_10base_tx_full = 0; 1269210284Sjmallett reg_autoneg_adver.s.advert_10base_tx_half = 0; 1270210284Sjmallett reg_autoneg_adver.s.advert_100base_tx_full = 0; 1271210284Sjmallett reg_autoneg_adver.s.advert_100base_tx_half = 0; 1272210284Sjmallett if (reg_status.s.capable_extended_status) 1273210284Sjmallett { 1274210284Sjmallett reg_control_1000.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000); 1275210284Sjmallett reg_control_1000.s.advert_1000base_t_full = 0; 1276210284Sjmallett reg_control_1000.s.advert_1000base_t_half = 0; 1277210284Sjmallett } 1278210284Sjmallett switch (link_info.s.speed) 1279210284Sjmallett { 1280210284Sjmallett case 10: 1281210284Sjmallett reg_autoneg_adver.s.advert_10base_tx_full = link_info.s.full_duplex; 1282210284Sjmallett reg_autoneg_adver.s.advert_10base_tx_half = !link_info.s.full_duplex; 1283210284Sjmallett break; 1284210284Sjmallett case 100: 1285210284Sjmallett reg_autoneg_adver.s.advert_100base_tx_full = link_info.s.full_duplex; 1286210284Sjmallett reg_autoneg_adver.s.advert_100base_tx_half = !link_info.s.full_duplex; 1287210284Sjmallett break; 1288210284Sjmallett case 1000: 1289210284Sjmallett reg_control_1000.s.advert_1000base_t_full = link_info.s.full_duplex; 1290210284Sjmallett reg_control_1000.s.advert_1000base_t_half = !link_info.s.full_duplex; 1291210284Sjmallett break; 1292210284Sjmallett } 1293210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER, reg_autoneg_adver.u16); 1294210284Sjmallett if (reg_status.s.capable_extended_status) 1295210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000, reg_control_1000.u16); 1296210284Sjmallett reg_control.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL); 1297210284Sjmallett reg_control.s.autoneg_enable = 1; 1298210284Sjmallett reg_control.s.restart_autoneg = 1; 1299210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); 1300210284Sjmallett } 1301210284Sjmallett else 1302210284Sjmallett { 1303210284Sjmallett cvmx_mdio_phy_reg_control_t reg_control; 1304210284Sjmallett reg_control.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL); 1305210284Sjmallett reg_control.s.autoneg_enable = 0; 1306210284Sjmallett reg_control.s.restart_autoneg = 1; 1307210284Sjmallett reg_control.s.duplex = link_info.s.full_duplex; 1308210284Sjmallett if (link_info.s.speed == 1000) 1309210284Sjmallett { 1310210284Sjmallett reg_control.s.speed_msb = 1; 1311210284Sjmallett reg_control.s.speed_lsb = 0; 1312210284Sjmallett } 1313210284Sjmallett else if (link_info.s.speed == 100) 1314210284Sjmallett { 1315210284Sjmallett reg_control.s.speed_msb = 0; 1316210284Sjmallett reg_control.s.speed_lsb = 1; 1317210284Sjmallett } 1318210284Sjmallett else if (link_info.s.speed == 10) 1319210284Sjmallett { 1320210284Sjmallett reg_control.s.speed_msb = 0; 1321210284Sjmallett reg_control.s.speed_lsb = 0; 1322210284Sjmallett } 1323210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); 1324210284Sjmallett } 1325210284Sjmallett return 0; 1326210284Sjmallett} 1327210284Sjmallett 1328210284Sjmallett 1329210284Sjmallett/** 1330210284Sjmallett * @INTERNAL 1331210284Sjmallett * This function is called by cvmx_helper_interface_probe() after it 1332210284Sjmallett * determines the number of ports Octeon can support on a specific 1333210284Sjmallett * interface. This function is the per board location to override 1334210284Sjmallett * this value. It is called with the number of ports Octeon might 1335210284Sjmallett * support and should return the number of actual ports on the 1336210284Sjmallett * board. 1337210284Sjmallett * 1338215990Sjmallett * This function must be modified for every new Octeon board. 1339210284Sjmallett * Internally it uses switch statements based on the cvmx_sysinfo 1340215990Sjmallett * data to determine board types and revisions. It relies on the 1341210284Sjmallett * fact that every Octeon board receives a unique board type 1342210284Sjmallett * enumeration from the bootloader. 1343210284Sjmallett * 1344210284Sjmallett * @param interface Interface to probe 1345210284Sjmallett * @param supported_ports 1346210284Sjmallett * Number of ports Octeon supports. 1347210284Sjmallett * 1348210284Sjmallett * @return Number of ports the actual board supports. Many times this will 1349210284Sjmallett * simple be "support_ports". 1350210284Sjmallett */ 1351210284Sjmallettint __cvmx_helper_board_interface_probe(int interface, int supported_ports) 1352210284Sjmallett{ 1353210284Sjmallett switch (cvmx_sysinfo_get()->board_type) 1354210284Sjmallett { 1355210284Sjmallett case CVMX_BOARD_TYPE_CN3005_EVB_HS5: 1356215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_A: 1357215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_U: 1358215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_G: 1359210284Sjmallett if (interface == 0) 1360210284Sjmallett return 2; 1361210284Sjmallett break; 1362210284Sjmallett case CVMX_BOARD_TYPE_BBGW_REF: 1363210284Sjmallett if (interface == 0) 1364210284Sjmallett return 2; 1365210284Sjmallett break; 1366210284Sjmallett case CVMX_BOARD_TYPE_NIC_XLE_4G: 1367210284Sjmallett if (interface == 0) 1368210284Sjmallett return 0; 1369210284Sjmallett break; 1370210284Sjmallett /* The 2nd interface on the EBH5600 is connected to the Marvel switch, 1371210284Sjmallett which we don't support. Disable ports connected to it */ 1372210284Sjmallett case CVMX_BOARD_TYPE_EBH5600: 1373210284Sjmallett if (interface == 1) 1374210284Sjmallett return 0; 1375210284Sjmallett break; 1376215990Sjmallett case CVMX_BOARD_TYPE_EBB5600: 1377215990Sjmallett#ifdef CVMX_ENABLE_PKO_FUNCTIONS 1378215990Sjmallett if (cvmx_helper_interface_get_mode(interface) == CVMX_HELPER_INTERFACE_MODE_PICMG) 1379215990Sjmallett return 0; 1380215990Sjmallett#endif 1381215990Sjmallett break; 1382242423Sjmallett case CVMX_BOARD_TYPE_EBT5600: 1383242423Sjmallett /* Disable loopback. */ 1384242423Sjmallett if (interface == 3) 1385242423Sjmallett return 0; 1386242423Sjmallett break; 1387215990Sjmallett case CVMX_BOARD_TYPE_EBT5810: 1388215990Sjmallett return 1; /* Two ports on each SPI: 1 hooked to MAC, 1 loopback 1389215990Sjmallett ** Loopback disabled by default. */ 1390232812Sjmallett case CVMX_BOARD_TYPE_NIC2E: 1391232812Sjmallett if (interface == 0) 1392232812Sjmallett return 2; 1393212844Sjmallett#if defined(OCTEON_VENDOR_LANNER) 1394212844Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR955: 1395212844Sjmallett if (interface == 1) 1396212844Sjmallett return 12; 1397212844Sjmallett break; 1398212844Sjmallett#endif 1399250428Simp#if defined(OCTEON_VENDOR_GEFES) 1400250428Simp case CVMX_BOARD_TYPE_CUST_TNPA5651X: 1401250428Simp if (interface < 2) /* interface can be EITHER 0 or 1 */ 1402250428Simp return 1;//always return 1 for XAUI and SGMII mode. 1403250428Simp break; 1404250428Simp case CVMX_BOARD_TYPE_CUST_TNPA56X4: 1405250428Simp if ((interface == 0) && 1406250428Simp (cvmx_helper_interface_get_mode(interface) == CVMX_HELPER_INTERFACE_MODE_SGMII)) 1407250428Simp { 1408250428Simp cvmx_pcsx_miscx_ctl_reg_t pcsx_miscx_ctl_reg; 1409250428Simp 1410250428Simp /* For this port we need to set the mode to 1000BaseX */ 1411250428Simp pcsx_miscx_ctl_reg.u64 = 1412250428Simp cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(0, interface)); 1413250428Simp pcsx_miscx_ctl_reg.cn56xx.mode = 1; 1414250428Simp cvmx_write_csr(CVMX_PCSX_MISCX_CTL_REG(0, interface), 1415250428Simp pcsx_miscx_ctl_reg.u64); 1416250428Simp pcsx_miscx_ctl_reg.u64 = 1417250428Simp cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(1, interface)); 1418250428Simp pcsx_miscx_ctl_reg.cn56xx.mode = 1; 1419250428Simp cvmx_write_csr(CVMX_PCSX_MISCX_CTL_REG(1, interface), 1420250428Simp pcsx_miscx_ctl_reg.u64); 1421250428Simp 1422250428Simp return 2; 1423250428Simp } 1424250428Simp break; 1425250428Simp#endif 1426210284Sjmallett } 1427210284Sjmallett#ifdef CVMX_BUILD_FOR_UBOOT 1428210284Sjmallett if (CVMX_HELPER_INTERFACE_MODE_SPI == cvmx_helper_interface_get_mode(interface) && getenv("disable_spi")) 1429210284Sjmallett return 0; 1430210284Sjmallett#endif 1431210284Sjmallett return supported_ports; 1432210284Sjmallett} 1433210284Sjmallett 1434210284Sjmallett 1435210284Sjmallett/** 1436210284Sjmallett * @INTERNAL 1437210284Sjmallett * Enable packet input/output from the hardware. This function is 1438210284Sjmallett * called after by cvmx_helper_packet_hardware_enable() to 1439210284Sjmallett * perform board specific initialization. For most boards 1440210284Sjmallett * nothing is needed. 1441210284Sjmallett * 1442210284Sjmallett * @param interface Interface to enable 1443210284Sjmallett * 1444210284Sjmallett * @return Zero on success, negative on failure 1445210284Sjmallett */ 1446210284Sjmallettint __cvmx_helper_board_hardware_enable(int interface) 1447210284Sjmallett{ 1448210284Sjmallett if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5) 1449210284Sjmallett { 1450210284Sjmallett if (interface == 0) 1451210284Sjmallett { 1452210284Sjmallett /* Different config for switch port */ 1453210284Sjmallett cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(1, interface), 0); 1454210284Sjmallett cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(1, interface), 0); 1455210284Sjmallett /* Boards with gigabit WAN ports need a different setting that is 1456210284Sjmallett compatible with 100 Mbit settings */ 1457210284Sjmallett cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 0xc); 1458210284Sjmallett cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 0xc); 1459210284Sjmallett } 1460210284Sjmallett } 1461215990Sjmallett else if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_LANAI2_U) 1462215990Sjmallett { 1463215990Sjmallett if (interface == 0) 1464215990Sjmallett { 1465215990Sjmallett cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 16); 1466215990Sjmallett cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 16); 1467215990Sjmallett } 1468215990Sjmallett } 1469210284Sjmallett else if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3010_EVB_HS5) 1470210284Sjmallett { 1471215990Sjmallett /* Broadcom PHYs require different ASX clocks. Unfortunately 1472210284Sjmallett many customer don't define a new board Id and simply 1473210284Sjmallett mangle the CN3010_EVB_HS5 */ 1474210284Sjmallett if (interface == 0) 1475210284Sjmallett { 1476210284Sjmallett /* Some customers boards use a hacked up bootloader that identifies them as 1477210284Sjmallett ** CN3010_EVB_HS5 evaluation boards. This leads to all kinds of configuration 1478210284Sjmallett ** problems. Detect one case, and print warning, while trying to do the right thing. 1479210284Sjmallett */ 1480210284Sjmallett int phy_addr = cvmx_helper_board_get_mii_address(0); 1481210284Sjmallett if (phy_addr != -1) 1482210284Sjmallett { 1483210284Sjmallett int phy_identifier = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 0x2); 1484210284Sjmallett /* Is it a Broadcom PHY? */ 1485210284Sjmallett if (phy_identifier == 0x0143) 1486210284Sjmallett { 1487210284Sjmallett cvmx_dprintf("\n"); 1488210284Sjmallett cvmx_dprintf("ERROR:\n"); 1489210284Sjmallett cvmx_dprintf("ERROR: Board type is CVMX_BOARD_TYPE_CN3010_EVB_HS5, but Broadcom PHY found.\n"); 1490210284Sjmallett cvmx_dprintf("ERROR: The board type is mis-configured, and software malfunctions are likely.\n"); 1491210284Sjmallett cvmx_dprintf("ERROR: All boards require a unique board type to identify them.\n"); 1492210284Sjmallett cvmx_dprintf("ERROR:\n"); 1493210284Sjmallett cvmx_dprintf("\n"); 1494210284Sjmallett cvmx_wait(1000000000); 1495210284Sjmallett cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 5); 1496210284Sjmallett cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 5); 1497210284Sjmallett } 1498210284Sjmallett } 1499210284Sjmallett } 1500210284Sjmallett } 1501245712Sjmallett#if defined(OCTEON_VENDOR_UBIQUITI) 1502245712Sjmallett else if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CUST_UBIQUITI_E100) 1503245712Sjmallett { 1504245712Sjmallett /* Configure ASX cloks for all ports on interface 0. */ 1505245712Sjmallett if (interface == 0) 1506245712Sjmallett { 1507245712Sjmallett int port; 1508245712Sjmallett 1509245712Sjmallett for (port = 0; port < 3; port++) { 1510245712Sjmallett cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface), 16); 1511245712Sjmallett cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, interface), 0); 1512245712Sjmallett } 1513245712Sjmallett } 1514245712Sjmallett } 1515245712Sjmallett#endif 1516210284Sjmallett return 0; 1517210284Sjmallett} 1518210284Sjmallett 1519215990Sjmallett 1520215990Sjmallett/** 1521215990Sjmallett * @INTERNAL 1522215990Sjmallett * Gets the clock type used for the USB block based on board type. 1523215990Sjmallett * Used by the USB code for auto configuration of clock type. 1524215990Sjmallett * 1525215990Sjmallett * @return USB clock type enumeration 1526215990Sjmallett */ 1527210284Sjmallettcvmx_helper_board_usb_clock_types_t __cvmx_helper_board_usb_get_clock_type(void) 1528210284Sjmallett{ 1529232812Sjmallett#if !defined(CVMX_BUILD_FOR_LINUX_KERNEL) && (!defined(__FreeBSD__) || !defined(_KERNEL)) 1530232812Sjmallett const void *fdt_addr = CASTPTR(const void *, cvmx_sysinfo_get()->fdt_addr); 1531232812Sjmallett int nodeoffset; 1532232812Sjmallett const void *nodep; 1533232812Sjmallett int len; 1534232812Sjmallett uint32_t speed = 0; 1535232812Sjmallett const char *type = NULL; 1536232812Sjmallett 1537232812Sjmallett if (fdt_addr) 1538232812Sjmallett { 1539232812Sjmallett nodeoffset = fdt_path_offset(fdt_addr, "/soc/uctl"); 1540232812Sjmallett if (nodeoffset < 0) 1541232812Sjmallett nodeoffset = fdt_path_offset(fdt_addr, "/soc/usbn"); 1542232812Sjmallett 1543232812Sjmallett if (nodeoffset >= 0) 1544232812Sjmallett { 1545232812Sjmallett nodep = fdt_getprop(fdt_addr, nodeoffset, "refclk-type", &len); 1546232812Sjmallett if (nodep != NULL && len > 0) 1547232812Sjmallett type = (const char *)nodep; 1548232812Sjmallett else 1549232812Sjmallett type = "unknown"; 1550232812Sjmallett nodep = fdt_getprop(fdt_addr, nodeoffset, "refclk-frequency", &len); 1551232812Sjmallett if (nodep != NULL && len == sizeof(uint32_t)) 1552232812Sjmallett speed = fdt32_to_cpu(*(int *)nodep); 1553232812Sjmallett else 1554232812Sjmallett speed = 0; 1555232812Sjmallett if (!strcmp(type, "crystal")) 1556232812Sjmallett { 1557232812Sjmallett if (speed == 0 || speed == 12000000) 1558232812Sjmallett return USB_CLOCK_TYPE_CRYSTAL_12; 1559232812Sjmallett else 1560232812Sjmallett printf("Warning: invalid crystal speed for USB clock type in FDT\n"); 1561232812Sjmallett } 1562232812Sjmallett else if (!strcmp(type, "external")) 1563232812Sjmallett { 1564232812Sjmallett switch (speed) { 1565232812Sjmallett case 12000000: 1566232812Sjmallett return USB_CLOCK_TYPE_REF_12; 1567232812Sjmallett case 24000000: 1568232812Sjmallett return USB_CLOCK_TYPE_REF_24; 1569232812Sjmallett case 0: 1570232812Sjmallett case 48000000: 1571232812Sjmallett return USB_CLOCK_TYPE_REF_48; 1572232812Sjmallett default: 1573232812Sjmallett printf("Warning: invalid USB clock speed of %u hz in FDT\n", speed); 1574232812Sjmallett } 1575232812Sjmallett } 1576232812Sjmallett else 1577232812Sjmallett printf("Warning: invalid USB reference clock type \"%s\" in FDT\n", type ? type : "NULL"); 1578232812Sjmallett } 1579232812Sjmallett } 1580232812Sjmallett#endif 1581215990Sjmallett switch (cvmx_sysinfo_get()->board_type) 1582215990Sjmallett { 1583215990Sjmallett case CVMX_BOARD_TYPE_BBGW_REF: 1584215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_A: 1585215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_U: 1586215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_G: 1587210311Sjmallett#if defined(OCTEON_VENDOR_LANNER) 1588250428Simp case CVMX_BOARD_TYPE_CUST_LANNER_MR320: 1589250428Simp case CVMX_BOARD_TYPE_CUST_LANNER_MR321X: 1590210311Sjmallett#endif 1591244985Sjmallett#if defined(OCTEON_VENDOR_UBIQUITI) 1592250428Simp case CVMX_BOARD_TYPE_CUST_UBIQUITI_E100: 1593244985Sjmallett#endif 1594229070Sgonzo#if defined(OCTEON_BOARD_CAPK_0100ND) 1595229070Sgonzo case CVMX_BOARD_TYPE_CN3010_EVB_HS5: 1596229070Sgonzo#endif 1597250428Simp#if defined(OCTEON_VENDOR_GEFES) /* All GEFES' boards use same xtal type */ 1598250428Simp case CVMX_BOARD_TYPE_TNPA3804: 1599250428Simp case CVMX_BOARD_TYPE_AT5810: 1600250428Simp case CVMX_BOARD_TYPE_WNPA3850: 1601250428Simp case CVMX_BOARD_TYPE_W3860: 1602250428Simp case CVMX_BOARD_TYPE_CUST_TNPA5804: 1603250428Simp case CVMX_BOARD_TYPE_CUST_W5434: 1604250428Simp case CVMX_BOARD_TYPE_CUST_W5650: 1605250428Simp case CVMX_BOARD_TYPE_CUST_W5800: 1606250428Simp case CVMX_BOARD_TYPE_CUST_W5651X: 1607250428Simp case CVMX_BOARD_TYPE_CUST_TNPA5651X: 1608250428Simp case CVMX_BOARD_TYPE_CUST_TNPA56X4: 1609250428Simp case CVMX_BOARD_TYPE_CUST_W63XX: 1610250428Simp#endif 1611232812Sjmallett case CVMX_BOARD_TYPE_NIC10E_66: 1612210284Sjmallett return USB_CLOCK_TYPE_CRYSTAL_12; 1613232812Sjmallett case CVMX_BOARD_TYPE_NIC10E: 1614232812Sjmallett return USB_CLOCK_TYPE_REF_12; 1615232812Sjmallett default: 1616232812Sjmallett break; 1617210284Sjmallett } 1618232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN6XXX) /* Most boards except NIC10e use a 12MHz crystal */ 1619232812Sjmallett || OCTEON_IS_MODEL(OCTEON_CNF7XXX)) 1620232812Sjmallett return USB_CLOCK_TYPE_CRYSTAL_12; 1621210284Sjmallett return USB_CLOCK_TYPE_REF_48; 1622210284Sjmallett} 1623210284Sjmallett 1624215990Sjmallett 1625215990Sjmallett/** 1626215990Sjmallett * @INTERNAL 1627215990Sjmallett * Adjusts the number of available USB ports on Octeon based on board 1628215990Sjmallett * specifics. 1629215990Sjmallett * 1630215990Sjmallett * @param supported_ports expected number of ports based on chip type; 1631215990Sjmallett * 1632215990Sjmallett * 1633215990Sjmallett * @return number of available usb ports, based on board specifics. 1634215990Sjmallett * Return value is supported_ports if function does not 1635215990Sjmallett * override. 1636215990Sjmallett */ 1637210284Sjmallettint __cvmx_helper_board_usb_get_num_ports(int supported_ports) 1638210284Sjmallett{ 1639215990Sjmallett switch (cvmx_sysinfo_get()->board_type) 1640215990Sjmallett { 1641210284Sjmallett case CVMX_BOARD_TYPE_NIC_XLE_4G: 1642232812Sjmallett case CVMX_BOARD_TYPE_NIC2E: 1643210284Sjmallett return 0; 1644210284Sjmallett } 1645210284Sjmallett 1646210284Sjmallett return supported_ports; 1647210284Sjmallett} 1648210284Sjmallett 1649210284Sjmallett 1650