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: 601320073Sjhibbits case CVMX_BOARD_TYPE_CUST_UBIQUITI_USG: 602244984Sjmallett if (ipd_port > 2) 603244984Sjmallett return -1; 604244984Sjmallett return (7 - ipd_port); 605244984Sjmallett#endif 606242116Sjmallett#if defined(OCTEON_VENDOR_RADISYS) 607242116Sjmallett case CVMX_BOARD_TYPE_CUST_RADISYS_RSYS4GBE: 608242116Sjmallett /* No MII. */ 609242116Sjmallett return -1; 610242116Sjmallett#endif 611250428Simp#if defined(OCTEON_VENDOR_GEFES) 612250428Simp case CVMX_BOARD_TYPE_AT5810: 613250428Simp return -1; 614250428Simp case CVMX_BOARD_TYPE_TNPA3804: 615250428Simp case CVMX_BOARD_TYPE_CUST_TNPA5804: 616250428Simp case CVMX_BOARD_TYPE_CUST_W5800: 617250428Simp case CVMX_BOARD_TYPE_WNPA3850: 618250428Simp case CVMX_BOARD_TYPE_W3860: 619250428Simp return -1;// RGMII boards should use inbad status 620250428Simp case CVMX_BOARD_TYPE_CUST_W5651X: 621250428Simp case CVMX_BOARD_TYPE_CUST_W5650: 622250428Simp case CVMX_BOARD_TYPE_CUST_TNPA56X4: 623250428Simp case CVMX_BOARD_TYPE_CUST_TNPA5651X: 624250428Simp case CVMX_BOARD_TYPE_CUST_W63XX: 625250428Simp return -1; /* No PHYs are connected to Octeon, PHYs inside of SFPs which is accessed over TWSI */ 626250428Simp case CVMX_BOARD_TYPE_CUST_W5434: 627250428Simp /* Board has 4 SGMII ports. 4 connect out 628250428Simp * must return the MII address of the PHY connected to each IPD port 629250428Simp */ 630250428Simp if ((ipd_port >= 16) && (ipd_port < 20)) 631250428Simp return ipd_port - 16 + 0x40; 632250428Simp else 633250428Simp return -1; 634250428Simp#endif 635210284Sjmallett } 636210284Sjmallett 637210284Sjmallett /* Some unknown board. Somebody forgot to update this function... */ 638215990Sjmallett cvmx_dprintf("%s: Unknown board type %d\n", 639215990Sjmallett __FUNCTION__, cvmx_sysinfo_get()->board_type); 640210284Sjmallett return -1; 641210284Sjmallett} 642215990Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 643215990SjmallettEXPORT_SYMBOL(cvmx_helper_board_get_mii_address); 644215990Sjmallett#endif 645210284Sjmallett 646232812Sjmallett/** 647232812Sjmallett * @INTERNAL 648232812Sjmallett * Get link state of marvell PHY 649232812Sjmallett */ 650232812Sjmallettstatic cvmx_helper_link_info_t __get_marvell_phy_link_state(int phy_addr) 651232812Sjmallett{ 652232812Sjmallett cvmx_helper_link_info_t result; 653232812Sjmallett int phy_status; 654210284Sjmallett 655232812Sjmallett result.u64 = 0; 656232812Sjmallett /*All the speed information can be read from register 17 in one go.*/ 657232812Sjmallett phy_status = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 17); 658232812Sjmallett 659232812Sjmallett /* If the resolve bit 11 isn't set, see if autoneg is turned off 660232812Sjmallett (bit 12, reg 0). The resolve bit doesn't get set properly when 661232812Sjmallett autoneg is off, so force it */ 662232812Sjmallett if ((phy_status & (1<<11)) == 0) 663232812Sjmallett { 664232812Sjmallett int auto_status = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 0); 665232812Sjmallett if ((auto_status & (1<<12)) == 0) 666232812Sjmallett phy_status |= 1<<11; 667232812Sjmallett } 668232812Sjmallett 669232812Sjmallett /* Only return a link if the PHY has finished auto negotiation 670232812Sjmallett and set the resolved bit (bit 11) */ 671232812Sjmallett if (phy_status & (1<<11)) 672232812Sjmallett { 673232812Sjmallett result.s.link_up = 1; 674232812Sjmallett result.s.full_duplex = ((phy_status>>13)&1); 675232812Sjmallett switch ((phy_status>>14)&3) 676232812Sjmallett { 677232812Sjmallett case 0: /* 10 Mbps */ 678232812Sjmallett result.s.speed = 10; 679232812Sjmallett break; 680232812Sjmallett case 1: /* 100 Mbps */ 681232812Sjmallett result.s.speed = 100; 682232812Sjmallett break; 683232812Sjmallett case 2: /* 1 Gbps */ 684232812Sjmallett result.s.speed = 1000; 685232812Sjmallett break; 686232812Sjmallett case 3: /* Illegal */ 687232812Sjmallett result.u64 = 0; 688232812Sjmallett break; 689232812Sjmallett } 690232812Sjmallett } 691232812Sjmallett return result; 692232812Sjmallett} 693232812Sjmallett 694210284Sjmallett/** 695210284Sjmallett * @INTERNAL 696232812Sjmallett * Get link state of broadcom PHY 697232812Sjmallett */ 698232812Sjmallettstatic cvmx_helper_link_info_t __get_broadcom_phy_link_state(int phy_addr) 699232812Sjmallett{ 700232812Sjmallett cvmx_helper_link_info_t result; 701232812Sjmallett int phy_status; 702232812Sjmallett 703232812Sjmallett result.u64 = 0; 704232812Sjmallett /* Below we are going to read SMI/MDIO register 0x19 which works 705232812Sjmallett on Broadcom parts */ 706232812Sjmallett phy_status = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 0x19); 707232812Sjmallett switch ((phy_status>>8) & 0x7) 708232812Sjmallett { 709232812Sjmallett case 0: 710232812Sjmallett result.u64 = 0; 711232812Sjmallett break; 712232812Sjmallett case 1: 713232812Sjmallett result.s.link_up = 1; 714232812Sjmallett result.s.full_duplex = 0; 715232812Sjmallett result.s.speed = 10; 716232812Sjmallett break; 717232812Sjmallett case 2: 718232812Sjmallett result.s.link_up = 1; 719232812Sjmallett result.s.full_duplex = 1; 720232812Sjmallett result.s.speed = 10; 721232812Sjmallett break; 722232812Sjmallett case 3: 723232812Sjmallett result.s.link_up = 1; 724232812Sjmallett result.s.full_duplex = 0; 725232812Sjmallett result.s.speed = 100; 726232812Sjmallett break; 727232812Sjmallett case 4: 728232812Sjmallett result.s.link_up = 1; 729232812Sjmallett result.s.full_duplex = 1; 730232812Sjmallett result.s.speed = 100; 731232812Sjmallett break; 732232812Sjmallett case 5: 733232812Sjmallett result.s.link_up = 1; 734232812Sjmallett result.s.full_duplex = 1; 735232812Sjmallett result.s.speed = 100; 736232812Sjmallett break; 737232812Sjmallett case 6: 738232812Sjmallett result.s.link_up = 1; 739232812Sjmallett result.s.full_duplex = 0; 740232812Sjmallett result.s.speed = 1000; 741232812Sjmallett break; 742232812Sjmallett case 7: 743232812Sjmallett result.s.link_up = 1; 744232812Sjmallett result.s.full_duplex = 1; 745232812Sjmallett result.s.speed = 1000; 746232812Sjmallett break; 747232812Sjmallett } 748232812Sjmallett return result; 749232812Sjmallett} 750232812Sjmallett 751232812Sjmallett 752232812Sjmallett/** 753232812Sjmallett * @INTERNAL 754232812Sjmallett * Get link state using inband status 755232812Sjmallett */ 756232812Sjmallettstatic cvmx_helper_link_info_t __get_inband_link_state(int ipd_port) 757232812Sjmallett{ 758232812Sjmallett cvmx_helper_link_info_t result; 759232812Sjmallett cvmx_gmxx_rxx_rx_inbnd_t inband_status; 760232812Sjmallett int interface = cvmx_helper_get_interface_num(ipd_port); 761232812Sjmallett int index = cvmx_helper_get_interface_index_num(ipd_port); 762232812Sjmallett 763232812Sjmallett result.u64 = 0; 764232812Sjmallett inband_status.u64 = cvmx_read_csr(CVMX_GMXX_RXX_RX_INBND(index, interface)); 765232812Sjmallett result.s.link_up = inband_status.s.status; 766232812Sjmallett result.s.full_duplex = inband_status.s.duplex; 767232812Sjmallett switch (inband_status.s.speed) 768232812Sjmallett { 769232812Sjmallett case 0: /* 10 Mbps */ 770232812Sjmallett result.s.speed = 10; 771232812Sjmallett break; 772232812Sjmallett case 1: /* 100 Mbps */ 773232812Sjmallett result.s.speed = 100; 774232812Sjmallett break; 775232812Sjmallett case 2: /* 1 Gbps */ 776232812Sjmallett result.s.speed = 1000; 777232812Sjmallett break; 778232812Sjmallett case 3: /* Illegal */ 779232812Sjmallett result.u64 = 0; 780232812Sjmallett break; 781232812Sjmallett } 782232812Sjmallett return result; 783232812Sjmallett} 784232812Sjmallett 785232812Sjmallett#if !defined(CVMX_BUILD_FOR_LINUX_KERNEL) && (!defined(__FreeBSD__) || !defined(_KERNEL)) 786232812Sjmallett/** 787232812Sjmallett * @INTERNAL 788232812Sjmallett * Switch MDIO mux to the specified port. 789232812Sjmallett */ 790232812Sjmallettstatic int __switch_mdio_mux(int ipd_port) 791232812Sjmallett{ 792232812Sjmallett /* This method is board specific and doesn't use the device tree 793232812Sjmallett information as SE doesn't implement MDIO MUX abstration */ 794232812Sjmallett switch (cvmx_sysinfo_get()->board_type) 795232812Sjmallett { 796232812Sjmallett case CVMX_BOARD_TYPE_EBB5600: 797232812Sjmallett { 798232812Sjmallett static unsigned char qlm_switch_addr = 0; 799232812Sjmallett /* Board has 1 management port */ 800232812Sjmallett if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT) 801232812Sjmallett return 0; 802232812Sjmallett /* Board has 8 SGMII ports. 4 connected QLM1, 4 connected QLM3 */ 803232812Sjmallett if ((ipd_port >= 0) && (ipd_port < 4)) 804232812Sjmallett { 805232812Sjmallett if (qlm_switch_addr != 0x3) 806232812Sjmallett { 807232812Sjmallett qlm_switch_addr = 0x3; /* QLM1 */ 808232812Sjmallett cvmx_twsix_write_ia(0, 0x71, 0, 1, 1, qlm_switch_addr); 809232812Sjmallett cvmx_wait_usec(11000); /* Let the write complete */ 810232812Sjmallett } 811232812Sjmallett return ipd_port+1 + (1<<8); 812232812Sjmallett } 813232812Sjmallett else if ((ipd_port >= 16) && (ipd_port < 20)) 814232812Sjmallett { 815232812Sjmallett if (qlm_switch_addr != 0xC) 816232812Sjmallett { 817232812Sjmallett qlm_switch_addr = 0xC; /* QLM3 */ 818232812Sjmallett cvmx_twsix_write_ia(0, 0x71, 0, 1, 1, qlm_switch_addr); 819232812Sjmallett cvmx_wait_usec(11000); /* Let the write complete */ 820232812Sjmallett } 821232812Sjmallett return ipd_port-16+1 + (1<<8); 822232812Sjmallett } 823232812Sjmallett else 824232812Sjmallett return -1; 825232812Sjmallett } 826232812Sjmallett case CVMX_BOARD_TYPE_EBB6600: 827232812Sjmallett { 828232812Sjmallett static unsigned char qlm_switch_addr = 0; 829232812Sjmallett int old_twsi_switch_reg; 830232812Sjmallett /* Board has 2 management ports */ 831232812Sjmallett if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && 832232812Sjmallett (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2))) 833232812Sjmallett return ipd_port - CVMX_HELPER_BOARD_MGMT_IPD_PORT + 4; 834232812Sjmallett if ((ipd_port >= 0) && (ipd_port < 4)) /* QLM 2 */ 835232812Sjmallett { 836232812Sjmallett if (qlm_switch_addr != 2) 837232812Sjmallett { 838232812Sjmallett int tries; 839232812Sjmallett qlm_switch_addr = 2; 840232812Sjmallett tries = 3; 841232812Sjmallett do { 842232812Sjmallett old_twsi_switch_reg = cvmx_twsix_read8(0, 0x70, 0); 843232812Sjmallett } while (tries-- > 0 && old_twsi_switch_reg < 0); 844232812Sjmallett /* Set I2C MUX to enable port expander */ 845232812Sjmallett cvmx_retry_i2c_write(0, 0x70, 0, 1, 0, 8); 846232812Sjmallett /* Set selecter to QLM 1 */ 847232812Sjmallett cvmx_retry_i2c_write(0, 0x38, 0, 1, 0, 0xff); 848232812Sjmallett /* disable port expander */ 849232812Sjmallett cvmx_retry_i2c_write(0, 0x70, 0, 1, 0, old_twsi_switch_reg); 850232812Sjmallett } 851232812Sjmallett return 0x101 + ipd_port; 852232812Sjmallett } 853232812Sjmallett else if ((ipd_port >= 16) && (ipd_port < 20)) /* QLM 1 */ 854232812Sjmallett { 855232812Sjmallett if (qlm_switch_addr != 1) 856232812Sjmallett { 857232812Sjmallett int tries; 858232812Sjmallett qlm_switch_addr = 1; 859232812Sjmallett tries = 3; 860232812Sjmallett do { 861232812Sjmallett old_twsi_switch_reg = cvmx_twsix_read8(0, 0x70, 0); 862232812Sjmallett } while (tries-- > 0 && old_twsi_switch_reg < 0); 863232812Sjmallett /* Set I2C MUX to enable port expander */ 864232812Sjmallett cvmx_retry_i2c_write(0, 0x70, 0, 1, 0, 8); 865232812Sjmallett /* Set selecter to QLM 2 */ 866232812Sjmallett cvmx_retry_i2c_write(0, 0x38, 0, 1, 0, 0xf7); 867232812Sjmallett /* disable port expander */ 868232812Sjmallett cvmx_retry_i2c_write(0, 0x70, 0, 1, 0, old_twsi_switch_reg); 869232812Sjmallett } 870232812Sjmallett return 0x101 + (ipd_port - 16); 871232812Sjmallett } else 872232812Sjmallett return -1; 873232812Sjmallett } 874232812Sjmallett case CVMX_BOARD_TYPE_EBB6100: 875232812Sjmallett { 876232812Sjmallett static char gpio_configured = 0; 877232812Sjmallett 878232812Sjmallett if (!gpio_configured) 879232812Sjmallett { 880232812Sjmallett cvmx_gpio_cfg(3, 1); 881232812Sjmallett gpio_configured = 1; 882232812Sjmallett } 883232812Sjmallett /* Board has 2 management ports */ 884232812Sjmallett if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && 885232812Sjmallett (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2))) 886232812Sjmallett return ipd_port - CVMX_HELPER_BOARD_MGMT_IPD_PORT + 4; 887232812Sjmallett if ((ipd_port >= 0) && (ipd_port < 4)) /* QLM 2 */ 888232812Sjmallett { 889232812Sjmallett cvmx_gpio_set(1ull << 3); 890232812Sjmallett return 0x101 + ipd_port; 891232812Sjmallett } 892232812Sjmallett else if ((ipd_port >= 16) && (ipd_port < 20)) /* QLM 0 */ 893232812Sjmallett { 894232812Sjmallett cvmx_gpio_clear(1ull << 3); 895232812Sjmallett return 0x101 + (ipd_port - 16); 896232812Sjmallett } 897232812Sjmallett else 898232812Sjmallett { 899232812Sjmallett printf("%s: Unknown ipd port 0x%x\n", __func__, ipd_port); 900232812Sjmallett return -1; 901232812Sjmallett } 902232812Sjmallett } 903232812Sjmallett default: 904232812Sjmallett { 905232812Sjmallett cvmx_dprintf("ERROR : unexpected mdio switch for board=%08x\n", 906232812Sjmallett cvmx_sysinfo_get()->board_type); 907232812Sjmallett return -1; 908232812Sjmallett } 909232812Sjmallett } 910232812Sjmallett /* should never get here */ 911232812Sjmallett return -1; 912232812Sjmallett} 913232812Sjmallett 914232812Sjmallett/** 915232812Sjmallett * @INTERNAL 916232812Sjmallett * This function is used ethernet ports link speed. This functions uses the 917232812Sjmallett * device tree information to determine the phy address and type of PHY. 918232812Sjmallett * The only supproted PHYs are Marvell and Broadcom. 919232812Sjmallett * 920232812Sjmallett * @param ipd_port IPD input port associated with the port we want to get link 921232812Sjmallett * status for. 922232812Sjmallett * 923232812Sjmallett * @return The ports link status. If the link isn't fully resolved, this must 924232812Sjmallett * return zero. 925232812Sjmallett */ 926232812Sjmallett 927232812Sjmallettcvmx_helper_link_info_t __cvmx_helper_board_link_get_from_dt(int ipd_port) 928232812Sjmallett{ 929232812Sjmallett cvmx_helper_link_info_t result; 930232812Sjmallett cvmx_phy_info_t phy_info; 931232812Sjmallett 932232812Sjmallett result.u64 = 0; 933232812Sjmallett if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) 934232812Sjmallett { 935232812Sjmallett /* The simulator gives you a simulated 1Gbps full duplex link */ 936232812Sjmallett result.s.link_up = 1; 937232812Sjmallett result.s.full_duplex = 1; 938232812Sjmallett result.s.speed = 1000; 939232812Sjmallett return result; 940232812Sjmallett } 941232812Sjmallett phy_info = __get_phy_info_from_dt(ipd_port); 942232812Sjmallett //cvmx_dprintf("ipd_port=%d phy_addr=%d dc=%d type=%d \n", ipd_port, 943232812Sjmallett // phy_info.phy_addr, phy_info.direct_connect, phy_info.phy_type); 944232812Sjmallett if (phy_info.phy_addr < 0) return result; 945232812Sjmallett 946232812Sjmallett if (phy_info.direct_connect == 0) 947232812Sjmallett __switch_mdio_mux(ipd_port); 948232812Sjmallett switch(phy_info.phy_type) 949232812Sjmallett { 950232812Sjmallett case BROADCOM_GENERIC_PHY: 951232812Sjmallett result = __get_broadcom_phy_link_state(phy_info.phy_addr); 952232812Sjmallett break; 953232812Sjmallett case MARVELL_GENERIC_PHY: 954232812Sjmallett result = __get_marvell_phy_link_state(phy_info.phy_addr); 955232812Sjmallett break; 956232812Sjmallett default: 957232812Sjmallett result = __get_inband_link_state(ipd_port); 958232812Sjmallett } 959232812Sjmallett return result; 960232812Sjmallett 961232812Sjmallett} 962232812Sjmallett#endif 963232812Sjmallett 964232812Sjmallett/** 965232812Sjmallett * @INTERNAL 966232812Sjmallett * This function invokes __cvmx_helper_board_link_get_from_dt when device tree 967232812Sjmallett * info is available. When the device tree information is not available then 968232812Sjmallett * this function is the board specific method of determining an 969210284Sjmallett * ethernet ports link speed. Most Octeon boards have Marvell PHYs 970210284Sjmallett * and are handled by the fall through case. This function must be 971210284Sjmallett * updated for boards that don't have the normal Marvell PHYs. 972210284Sjmallett * 973210284Sjmallett * This function must be modified for every new Octeon board. 974210284Sjmallett * Internally it uses switch statements based on the cvmx_sysinfo 975210284Sjmallett * data to determine board types and revisions. It relies on the 976210284Sjmallett * fact that every Octeon board receives a unique board type 977210284Sjmallett * enumeration from the bootloader. 978210284Sjmallett * 979210284Sjmallett * @param ipd_port IPD input port associated with the port we want to get link 980210284Sjmallett * status for. 981210284Sjmallett * 982210284Sjmallett * @return The ports link status. If the link isn't fully resolved, this must 983210284Sjmallett * return zero. 984210284Sjmallett */ 985210284Sjmallettcvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port) 986210284Sjmallett{ 987210284Sjmallett cvmx_helper_link_info_t result; 988210284Sjmallett int phy_addr; 989210284Sjmallett int is_broadcom_phy = 0; 990210284Sjmallett 991232812Sjmallett#if !defined(CVMX_BUILD_FOR_LINUX_KERNEL) && (!defined(__FreeBSD__) || !defined(_KERNEL)) 992232812Sjmallett if (cvmx_sysinfo_get()->fdt_addr) 993232812Sjmallett { 994232812Sjmallett return __cvmx_helper_board_link_get_from_dt(ipd_port); 995232812Sjmallett } 996232812Sjmallett#endif 997232812Sjmallett 998210284Sjmallett /* Give the user a chance to override the processing of this function */ 999210284Sjmallett if (cvmx_override_board_link_get) 1000210284Sjmallett return cvmx_override_board_link_get(ipd_port); 1001210284Sjmallett 1002210284Sjmallett /* Unless we fix it later, all links are defaulted to down */ 1003210284Sjmallett result.u64 = 0; 1004210284Sjmallett 1005210311Sjmallett#if !defined(OCTEON_BOARD_CAPK_0100ND) 1006210284Sjmallett /* This switch statement should handle all ports that either don't use 1007210284Sjmallett Marvell PHYS, or don't support in-band status */ 1008210284Sjmallett switch (cvmx_sysinfo_get()->board_type) 1009210284Sjmallett { 1010210284Sjmallett case CVMX_BOARD_TYPE_SIM: 1011210284Sjmallett /* The simulator gives you a simulated 1Gbps full duplex link */ 1012210284Sjmallett result.s.link_up = 1; 1013210284Sjmallett result.s.full_duplex = 1; 1014210284Sjmallett result.s.speed = 1000; 1015210284Sjmallett return result; 1016215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_A: 1017215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_U: 1018215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_G: 1019215990Sjmallett break; 1020210284Sjmallett case CVMX_BOARD_TYPE_EBH3100: 1021210284Sjmallett case CVMX_BOARD_TYPE_CN3010_EVB_HS5: 1022210284Sjmallett case CVMX_BOARD_TYPE_CN3005_EVB_HS5: 1023250428Simp#if !defined(OCTEON_VENDOR_GEFES) 1024210284Sjmallett case CVMX_BOARD_TYPE_CN3020_EVB_HS5: 1025250428Simp#endif 1026210284Sjmallett /* Port 1 on these boards is always Gigabit */ 1027210284Sjmallett if (ipd_port == 1) 1028210284Sjmallett { 1029210284Sjmallett result.s.link_up = 1; 1030210284Sjmallett result.s.full_duplex = 1; 1031210284Sjmallett result.s.speed = 1000; 1032210284Sjmallett return result; 1033210284Sjmallett } 1034210284Sjmallett /* Fall through to the generic code below */ 1035210284Sjmallett break; 1036242423Sjmallett case CVMX_BOARD_TYPE_EBT5600: 1037215990Sjmallett case CVMX_BOARD_TYPE_EBH5600: 1038215990Sjmallett case CVMX_BOARD_TYPE_EBH5601: 1039215990Sjmallett case CVMX_BOARD_TYPE_EBH5610: 1040215990Sjmallett /* Board has 1 management ports */ 1041215990Sjmallett if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT) 1042215990Sjmallett is_broadcom_phy = 1; 1043215990Sjmallett break; 1044215990Sjmallett case CVMX_BOARD_TYPE_EBH5200: 1045215990Sjmallett case CVMX_BOARD_TYPE_EBH5201: 1046215990Sjmallett case CVMX_BOARD_TYPE_EBT5200: 1047215990Sjmallett /* Board has 2 management ports */ 1048215990Sjmallett if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2))) 1049215990Sjmallett is_broadcom_phy = 1; 1050215990Sjmallett break; 1051232812Sjmallett case CVMX_BOARD_TYPE_EBB6100: 1052215990Sjmallett case CVMX_BOARD_TYPE_EBB6300: /* Only for MII mode, with PHY addresses 0/1. Default is RGMII*/ 1053232812Sjmallett case CVMX_BOARD_TYPE_EBB6600: /* Only for MII mode, with PHY addresses 0/1. Default is RGMII*/ 1054215990Sjmallett if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2)) 1055215990Sjmallett && cvmx_helper_board_get_mii_address(ipd_port) >= 0 && cvmx_helper_board_get_mii_address(ipd_port) <= 1) 1056215990Sjmallett is_broadcom_phy = 1; 1057215990Sjmallett break; 1058232812Sjmallett case CVMX_BOARD_TYPE_EP6300C: 1059232812Sjmallett is_broadcom_phy = 1; 1060232812Sjmallett break; 1061210284Sjmallett case CVMX_BOARD_TYPE_CUST_NB5: 1062210284Sjmallett /* Port 1 on these boards is always Gigabit */ 1063210284Sjmallett if (ipd_port == 1) 1064210284Sjmallett { 1065210284Sjmallett result.s.link_up = 1; 1066210284Sjmallett result.s.full_duplex = 1; 1067210284Sjmallett result.s.speed = 1000; 1068210284Sjmallett return result; 1069210284Sjmallett } 1070210284Sjmallett else /* The other port uses a broadcom PHY */ 1071210284Sjmallett is_broadcom_phy = 1; 1072210284Sjmallett break; 1073210284Sjmallett case CVMX_BOARD_TYPE_BBGW_REF: 1074210284Sjmallett /* Port 1 on these boards is always Gigabit */ 1075210284Sjmallett if (ipd_port == 2) 1076215990Sjmallett { 1077210284Sjmallett /* Port 2 is not hooked up */ 1078210284Sjmallett result.u64 = 0; 1079210284Sjmallett return result; 1080210284Sjmallett } 1081210284Sjmallett else 1082210284Sjmallett { 1083210284Sjmallett /* Ports 0 and 1 connect to the switch */ 1084210284Sjmallett result.s.link_up = 1; 1085210284Sjmallett result.s.full_duplex = 1; 1086210284Sjmallett result.s.speed = 1000; 1087210284Sjmallett return result; 1088210284Sjmallett } 1089232812Sjmallett case CVMX_BOARD_TYPE_NIC4E: 1090232812Sjmallett case CVMX_BOARD_TYPE_NIC2E: 1091232812Sjmallett is_broadcom_phy = 1; 1092210284Sjmallett break; 1093210311Sjmallett /* Private vendor-defined boards. */ 1094210311Sjmallett#if defined(OCTEON_VENDOR_LANNER) 1095215014Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR730: 1096215014Sjmallett /* Ports are BCM5482S */ 1097215014Sjmallett is_broadcom_phy = 1; 1098215014Sjmallett break; 1099210311Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR320: 1100216476Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR321X: 1101210311Sjmallett /* Port 0 connects to the switch */ 1102210311Sjmallett if (ipd_port == 0) 1103210311Sjmallett { 1104210311Sjmallett result.s.link_up = 1; 1105210311Sjmallett result.s.full_duplex = 1; 1106210311Sjmallett result.s.speed = 1000; 1107210311Sjmallett return result; 1108210311Sjmallett } 1109210311Sjmallett break; 1110210311Sjmallett#endif 1111250428Simp#if defined(OCTEON_VENDOR_GEFES) 1112250428Simp case CVMX_BOARD_TYPE_CUST_TNPA5651X: 1113250428Simp /* Since we don't auto-negotiate... 1Gbps full duplex link */ 1114250428Simp result.s.link_up = 1; 1115250428Simp result.s.full_duplex = 1; 1116250428Simp result.s.speed = 1000; 1117250428Simp return result; 1118250428Simp break; 1119250428Simp#endif 1120210284Sjmallett } 1121210311Sjmallett#endif 1122210284Sjmallett 1123210284Sjmallett phy_addr = cvmx_helper_board_get_mii_address(ipd_port); 1124232812Sjmallett //cvmx_dprintf("ipd_port=%d phy_addr=%d broadcom=%d\n", 1125232812Sjmallett // ipd_port, phy_addr, is_broadcom_phy); 1126210284Sjmallett if (phy_addr != -1) 1127210284Sjmallett { 1128210284Sjmallett if (is_broadcom_phy) 1129210284Sjmallett { 1130232812Sjmallett result = __get_broadcom_phy_link_state(phy_addr); 1131210284Sjmallett } 1132210284Sjmallett else 1133210284Sjmallett { 1134232812Sjmallett /* This code assumes we are using a Marvell Gigabit PHY. */ 1135232812Sjmallett result = __get_marvell_phy_link_state(phy_addr); 1136210284Sjmallett } 1137210284Sjmallett } 1138232812Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN58XX) 1139232812Sjmallett || OCTEON_IS_MODEL(OCTEON_CN50XX)) 1140210284Sjmallett { 1141210284Sjmallett /* We don't have a PHY address, so attempt to use in-band status. It is 1142210284Sjmallett really important that boards not supporting in-band status never get 1143210284Sjmallett here. Reading broken in-band status tends to do bad things */ 1144232812Sjmallett result = __get_inband_link_state(ipd_port); 1145210284Sjmallett } 1146250428Simp#if defined(OCTEON_VENDOR_GEFES) 1147250428Simp else if( (OCTEON_IS_MODEL(OCTEON_CN56XX)) || (OCTEON_IS_MODEL(OCTEON_CN63XX)) ) 1148250428Simp { 1149250428Simp int interface = cvmx_helper_get_interface_num(ipd_port); 1150250428Simp int index = cvmx_helper_get_interface_index_num(ipd_port); 1151250428Simp cvmx_pcsx_miscx_ctl_reg_t mode_type; 1152250428Simp cvmx_pcsx_mrx_status_reg_t mrx_status; 1153250428Simp cvmx_pcsx_anx_adv_reg_t anxx_adv; 1154250428Simp cvmx_pcsx_sgmx_lp_adv_reg_t sgmii_inband_status; 1155250428Simp 1156250428Simp anxx_adv.u64 = cvmx_read_csr(CVMX_PCSX_ANX_ADV_REG(index, interface)); 1157250428Simp mrx_status.u64 = cvmx_read_csr(CVMX_PCSX_MRX_STATUS_REG(index, interface)); 1158250428Simp 1159250428Simp mode_type.u64 = cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface)); 1160250428Simp 1161250428Simp /* Read Octeon's inband status */ 1162250428Simp sgmii_inband_status.u64 = cvmx_read_csr(CVMX_PCSX_SGMX_LP_ADV_REG(index, interface)); 1163250428Simp 1164250428Simp result.s.link_up = sgmii_inband_status.s.link; 1165250428Simp result.s.full_duplex = sgmii_inband_status.s.dup; 1166250428Simp switch (sgmii_inband_status.s.speed) 1167250428Simp { 1168250428Simp case 0: /* 10 Mbps */ 1169250428Simp result.s.speed = 10; 1170250428Simp break; 1171250428Simp case 1: /* 100 Mbps */ 1172250428Simp result.s.speed = 100; 1173250428Simp break; 1174250428Simp case 2: /* 1 Gbps */ 1175250428Simp result.s.speed = 1000; 1176250428Simp break; 1177250428Simp case 3: /* Illegal */ 1178250428Simp result.s.speed = 0; 1179250428Simp result.s.link_up = 0; 1180250428Simp break; 1181250428Simp } 1182250428Simp } 1183250428Simp#endif 1184210284Sjmallett else 1185210284Sjmallett { 1186210284Sjmallett /* We don't have a PHY address and we don't have in-band status. There 1187210284Sjmallett is no way to determine the link speed. Return down assuming this 1188210284Sjmallett port isn't wired */ 1189210284Sjmallett result.u64 = 0; 1190210284Sjmallett } 1191210284Sjmallett 1192210284Sjmallett /* If link is down, return all fields as zero. */ 1193210284Sjmallett if (!result.s.link_up) 1194210284Sjmallett result.u64 = 0; 1195210284Sjmallett 1196210284Sjmallett return result; 1197210284Sjmallett} 1198210284Sjmallett 1199210284Sjmallett 1200210284Sjmallett/** 1201210284Sjmallett * This function as a board specific method of changing the PHY 1202215990Sjmallett * speed, duplex, and autonegotiation. This programs the PHY and 1203210284Sjmallett * not Octeon. This can be used to force Octeon's links to 1204210284Sjmallett * specific settings. 1205210284Sjmallett * 1206210284Sjmallett * @param phy_addr The address of the PHY to program 1207215990Sjmallett * @param link_flags 1208215990Sjmallett * Flags to control autonegotiation. Bit 0 is autonegotiation 1209215990Sjmallett * enable/disable to maintain backward compatibility. 1210215990Sjmallett * @param link_info Link speed to program. If the speed is zero and autonegotiation 1211210284Sjmallett * is enabled, all possible negotiation speeds are advertised. 1212210284Sjmallett * 1213210284Sjmallett * @return Zero on success, negative on failure 1214210284Sjmallett */ 1215210284Sjmallettint cvmx_helper_board_link_set_phy(int phy_addr, cvmx_helper_board_set_phy_link_flags_types_t link_flags, 1216210284Sjmallett cvmx_helper_link_info_t link_info) 1217210284Sjmallett{ 1218210284Sjmallett 1219210284Sjmallett /* Set the flow control settings based on link_flags */ 1220210284Sjmallett if ((link_flags & set_phy_link_flags_flow_control_mask) != set_phy_link_flags_flow_control_dont_touch) 1221210284Sjmallett { 1222210284Sjmallett cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; 1223210284Sjmallett reg_autoneg_adver.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER); 1224210284Sjmallett reg_autoneg_adver.s.asymmetric_pause = (link_flags & set_phy_link_flags_flow_control_mask) == set_phy_link_flags_flow_control_enable; 1225210284Sjmallett reg_autoneg_adver.s.pause = (link_flags & set_phy_link_flags_flow_control_mask) == set_phy_link_flags_flow_control_enable; 1226210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER, reg_autoneg_adver.u16); 1227210284Sjmallett } 1228210284Sjmallett 1229210284Sjmallett /* If speed isn't set and autoneg is on advertise all supported modes */ 1230210284Sjmallett if ((link_flags & set_phy_link_flags_autoneg) && (link_info.s.speed == 0)) 1231210284Sjmallett { 1232210284Sjmallett cvmx_mdio_phy_reg_control_t reg_control; 1233210284Sjmallett cvmx_mdio_phy_reg_status_t reg_status; 1234210284Sjmallett cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; 1235210284Sjmallett cvmx_mdio_phy_reg_extended_status_t reg_extended_status; 1236210284Sjmallett cvmx_mdio_phy_reg_control_1000_t reg_control_1000; 1237210284Sjmallett 1238210284Sjmallett reg_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_STATUS); 1239210284Sjmallett reg_autoneg_adver.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER); 1240210284Sjmallett reg_autoneg_adver.s.advert_100base_t4 = reg_status.s.capable_100base_t4; 1241210284Sjmallett reg_autoneg_adver.s.advert_10base_tx_full = reg_status.s.capable_10_full; 1242210284Sjmallett reg_autoneg_adver.s.advert_10base_tx_half = reg_status.s.capable_10_half; 1243210284Sjmallett reg_autoneg_adver.s.advert_100base_tx_full = reg_status.s.capable_100base_x_full; 1244210284Sjmallett reg_autoneg_adver.s.advert_100base_tx_half = reg_status.s.capable_100base_x_half; 1245210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER, reg_autoneg_adver.u16); 1246210284Sjmallett if (reg_status.s.capable_extended_status) 1247210284Sjmallett { 1248210284Sjmallett reg_extended_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_EXTENDED_STATUS); 1249210284Sjmallett reg_control_1000.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000); 1250210284Sjmallett reg_control_1000.s.advert_1000base_t_full = reg_extended_status.s.capable_1000base_t_full; 1251210284Sjmallett reg_control_1000.s.advert_1000base_t_half = reg_extended_status.s.capable_1000base_t_half; 1252210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000, reg_control_1000.u16); 1253210284Sjmallett } 1254210284Sjmallett reg_control.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL); 1255210284Sjmallett reg_control.s.autoneg_enable = 1; 1256210284Sjmallett reg_control.s.restart_autoneg = 1; 1257210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); 1258210284Sjmallett } 1259210284Sjmallett else if ((link_flags & set_phy_link_flags_autoneg)) 1260210284Sjmallett { 1261210284Sjmallett cvmx_mdio_phy_reg_control_t reg_control; 1262210284Sjmallett cvmx_mdio_phy_reg_status_t reg_status; 1263210284Sjmallett cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; 1264210284Sjmallett cvmx_mdio_phy_reg_control_1000_t reg_control_1000; 1265210284Sjmallett 1266210284Sjmallett reg_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_STATUS); 1267210284Sjmallett reg_autoneg_adver.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER); 1268210284Sjmallett reg_autoneg_adver.s.advert_100base_t4 = 0; 1269210284Sjmallett reg_autoneg_adver.s.advert_10base_tx_full = 0; 1270210284Sjmallett reg_autoneg_adver.s.advert_10base_tx_half = 0; 1271210284Sjmallett reg_autoneg_adver.s.advert_100base_tx_full = 0; 1272210284Sjmallett reg_autoneg_adver.s.advert_100base_tx_half = 0; 1273210284Sjmallett if (reg_status.s.capable_extended_status) 1274210284Sjmallett { 1275210284Sjmallett reg_control_1000.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000); 1276210284Sjmallett reg_control_1000.s.advert_1000base_t_full = 0; 1277210284Sjmallett reg_control_1000.s.advert_1000base_t_half = 0; 1278210284Sjmallett } 1279210284Sjmallett switch (link_info.s.speed) 1280210284Sjmallett { 1281210284Sjmallett case 10: 1282210284Sjmallett reg_autoneg_adver.s.advert_10base_tx_full = link_info.s.full_duplex; 1283210284Sjmallett reg_autoneg_adver.s.advert_10base_tx_half = !link_info.s.full_duplex; 1284210284Sjmallett break; 1285210284Sjmallett case 100: 1286210284Sjmallett reg_autoneg_adver.s.advert_100base_tx_full = link_info.s.full_duplex; 1287210284Sjmallett reg_autoneg_adver.s.advert_100base_tx_half = !link_info.s.full_duplex; 1288210284Sjmallett break; 1289210284Sjmallett case 1000: 1290210284Sjmallett reg_control_1000.s.advert_1000base_t_full = link_info.s.full_duplex; 1291210284Sjmallett reg_control_1000.s.advert_1000base_t_half = !link_info.s.full_duplex; 1292210284Sjmallett break; 1293210284Sjmallett } 1294210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER, reg_autoneg_adver.u16); 1295210284Sjmallett if (reg_status.s.capable_extended_status) 1296210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000, reg_control_1000.u16); 1297210284Sjmallett reg_control.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL); 1298210284Sjmallett reg_control.s.autoneg_enable = 1; 1299210284Sjmallett reg_control.s.restart_autoneg = 1; 1300210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); 1301210284Sjmallett } 1302210284Sjmallett else 1303210284Sjmallett { 1304210284Sjmallett cvmx_mdio_phy_reg_control_t reg_control; 1305210284Sjmallett reg_control.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL); 1306210284Sjmallett reg_control.s.autoneg_enable = 0; 1307210284Sjmallett reg_control.s.restart_autoneg = 1; 1308210284Sjmallett reg_control.s.duplex = link_info.s.full_duplex; 1309210284Sjmallett if (link_info.s.speed == 1000) 1310210284Sjmallett { 1311210284Sjmallett reg_control.s.speed_msb = 1; 1312210284Sjmallett reg_control.s.speed_lsb = 0; 1313210284Sjmallett } 1314210284Sjmallett else if (link_info.s.speed == 100) 1315210284Sjmallett { 1316210284Sjmallett reg_control.s.speed_msb = 0; 1317210284Sjmallett reg_control.s.speed_lsb = 1; 1318210284Sjmallett } 1319210284Sjmallett else if (link_info.s.speed == 10) 1320210284Sjmallett { 1321210284Sjmallett reg_control.s.speed_msb = 0; 1322210284Sjmallett reg_control.s.speed_lsb = 0; 1323210284Sjmallett } 1324210284Sjmallett cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); 1325210284Sjmallett } 1326210284Sjmallett return 0; 1327210284Sjmallett} 1328210284Sjmallett 1329210284Sjmallett 1330210284Sjmallett/** 1331210284Sjmallett * @INTERNAL 1332210284Sjmallett * This function is called by cvmx_helper_interface_probe() after it 1333210284Sjmallett * determines the number of ports Octeon can support on a specific 1334210284Sjmallett * interface. This function is the per board location to override 1335210284Sjmallett * this value. It is called with the number of ports Octeon might 1336210284Sjmallett * support and should return the number of actual ports on the 1337210284Sjmallett * board. 1338210284Sjmallett * 1339215990Sjmallett * This function must be modified for every new Octeon board. 1340210284Sjmallett * Internally it uses switch statements based on the cvmx_sysinfo 1341215990Sjmallett * data to determine board types and revisions. It relies on the 1342210284Sjmallett * fact that every Octeon board receives a unique board type 1343210284Sjmallett * enumeration from the bootloader. 1344210284Sjmallett * 1345210284Sjmallett * @param interface Interface to probe 1346210284Sjmallett * @param supported_ports 1347210284Sjmallett * Number of ports Octeon supports. 1348210284Sjmallett * 1349210284Sjmallett * @return Number of ports the actual board supports. Many times this will 1350210284Sjmallett * simple be "support_ports". 1351210284Sjmallett */ 1352210284Sjmallettint __cvmx_helper_board_interface_probe(int interface, int supported_ports) 1353210284Sjmallett{ 1354210284Sjmallett switch (cvmx_sysinfo_get()->board_type) 1355210284Sjmallett { 1356210284Sjmallett case CVMX_BOARD_TYPE_CN3005_EVB_HS5: 1357215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_A: 1358215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_U: 1359215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_G: 1360210284Sjmallett if (interface == 0) 1361210284Sjmallett return 2; 1362210284Sjmallett break; 1363210284Sjmallett case CVMX_BOARD_TYPE_BBGW_REF: 1364210284Sjmallett if (interface == 0) 1365210284Sjmallett return 2; 1366210284Sjmallett break; 1367210284Sjmallett case CVMX_BOARD_TYPE_NIC_XLE_4G: 1368210284Sjmallett if (interface == 0) 1369210284Sjmallett return 0; 1370210284Sjmallett break; 1371210284Sjmallett /* The 2nd interface on the EBH5600 is connected to the Marvel switch, 1372210284Sjmallett which we don't support. Disable ports connected to it */ 1373210284Sjmallett case CVMX_BOARD_TYPE_EBH5600: 1374210284Sjmallett if (interface == 1) 1375210284Sjmallett return 0; 1376210284Sjmallett break; 1377215990Sjmallett case CVMX_BOARD_TYPE_EBB5600: 1378215990Sjmallett#ifdef CVMX_ENABLE_PKO_FUNCTIONS 1379215990Sjmallett if (cvmx_helper_interface_get_mode(interface) == CVMX_HELPER_INTERFACE_MODE_PICMG) 1380215990Sjmallett return 0; 1381215990Sjmallett#endif 1382215990Sjmallett break; 1383242423Sjmallett case CVMX_BOARD_TYPE_EBT5600: 1384242423Sjmallett /* Disable loopback. */ 1385242423Sjmallett if (interface == 3) 1386242423Sjmallett return 0; 1387242423Sjmallett break; 1388215990Sjmallett case CVMX_BOARD_TYPE_EBT5810: 1389215990Sjmallett return 1; /* Two ports on each SPI: 1 hooked to MAC, 1 loopback 1390215990Sjmallett ** Loopback disabled by default. */ 1391232812Sjmallett case CVMX_BOARD_TYPE_NIC2E: 1392232812Sjmallett if (interface == 0) 1393232812Sjmallett return 2; 1394212844Sjmallett#if defined(OCTEON_VENDOR_LANNER) 1395212844Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR955: 1396212844Sjmallett if (interface == 1) 1397212844Sjmallett return 12; 1398212844Sjmallett break; 1399212844Sjmallett#endif 1400250428Simp#if defined(OCTEON_VENDOR_GEFES) 1401250428Simp case CVMX_BOARD_TYPE_CUST_TNPA5651X: 1402250428Simp if (interface < 2) /* interface can be EITHER 0 or 1 */ 1403250428Simp return 1;//always return 1 for XAUI and SGMII mode. 1404250428Simp break; 1405250428Simp case CVMX_BOARD_TYPE_CUST_TNPA56X4: 1406250428Simp if ((interface == 0) && 1407250428Simp (cvmx_helper_interface_get_mode(interface) == CVMX_HELPER_INTERFACE_MODE_SGMII)) 1408250428Simp { 1409250428Simp cvmx_pcsx_miscx_ctl_reg_t pcsx_miscx_ctl_reg; 1410250428Simp 1411250428Simp /* For this port we need to set the mode to 1000BaseX */ 1412250428Simp pcsx_miscx_ctl_reg.u64 = 1413250428Simp cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(0, interface)); 1414250428Simp pcsx_miscx_ctl_reg.cn56xx.mode = 1; 1415250428Simp cvmx_write_csr(CVMX_PCSX_MISCX_CTL_REG(0, interface), 1416250428Simp pcsx_miscx_ctl_reg.u64); 1417250428Simp pcsx_miscx_ctl_reg.u64 = 1418250428Simp cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(1, interface)); 1419250428Simp pcsx_miscx_ctl_reg.cn56xx.mode = 1; 1420250428Simp cvmx_write_csr(CVMX_PCSX_MISCX_CTL_REG(1, interface), 1421250428Simp pcsx_miscx_ctl_reg.u64); 1422250428Simp 1423250428Simp return 2; 1424250428Simp } 1425250428Simp break; 1426250428Simp#endif 1427210284Sjmallett } 1428210284Sjmallett#ifdef CVMX_BUILD_FOR_UBOOT 1429210284Sjmallett if (CVMX_HELPER_INTERFACE_MODE_SPI == cvmx_helper_interface_get_mode(interface) && getenv("disable_spi")) 1430210284Sjmallett return 0; 1431210284Sjmallett#endif 1432210284Sjmallett return supported_ports; 1433210284Sjmallett} 1434210284Sjmallett 1435210284Sjmallett 1436210284Sjmallett/** 1437210284Sjmallett * @INTERNAL 1438210284Sjmallett * Enable packet input/output from the hardware. This function is 1439210284Sjmallett * called after by cvmx_helper_packet_hardware_enable() to 1440210284Sjmallett * perform board specific initialization. For most boards 1441210284Sjmallett * nothing is needed. 1442210284Sjmallett * 1443210284Sjmallett * @param interface Interface to enable 1444210284Sjmallett * 1445210284Sjmallett * @return Zero on success, negative on failure 1446210284Sjmallett */ 1447210284Sjmallettint __cvmx_helper_board_hardware_enable(int interface) 1448210284Sjmallett{ 1449210284Sjmallett if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5) 1450210284Sjmallett { 1451210284Sjmallett if (interface == 0) 1452210284Sjmallett { 1453210284Sjmallett /* Different config for switch port */ 1454210284Sjmallett cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(1, interface), 0); 1455210284Sjmallett cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(1, interface), 0); 1456210284Sjmallett /* Boards with gigabit WAN ports need a different setting that is 1457210284Sjmallett compatible with 100 Mbit settings */ 1458210284Sjmallett cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 0xc); 1459210284Sjmallett cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 0xc); 1460210284Sjmallett } 1461210284Sjmallett } 1462215990Sjmallett else if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_LANAI2_U) 1463215990Sjmallett { 1464215990Sjmallett if (interface == 0) 1465215990Sjmallett { 1466215990Sjmallett cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 16); 1467215990Sjmallett cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 16); 1468215990Sjmallett } 1469215990Sjmallett } 1470210284Sjmallett else if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3010_EVB_HS5) 1471210284Sjmallett { 1472215990Sjmallett /* Broadcom PHYs require different ASX clocks. Unfortunately 1473210284Sjmallett many customer don't define a new board Id and simply 1474210284Sjmallett mangle the CN3010_EVB_HS5 */ 1475210284Sjmallett if (interface == 0) 1476210284Sjmallett { 1477210284Sjmallett /* Some customers boards use a hacked up bootloader that identifies them as 1478210284Sjmallett ** CN3010_EVB_HS5 evaluation boards. This leads to all kinds of configuration 1479210284Sjmallett ** problems. Detect one case, and print warning, while trying to do the right thing. 1480210284Sjmallett */ 1481210284Sjmallett int phy_addr = cvmx_helper_board_get_mii_address(0); 1482210284Sjmallett if (phy_addr != -1) 1483210284Sjmallett { 1484210284Sjmallett int phy_identifier = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 0x2); 1485210284Sjmallett /* Is it a Broadcom PHY? */ 1486210284Sjmallett if (phy_identifier == 0x0143) 1487210284Sjmallett { 1488210284Sjmallett cvmx_dprintf("\n"); 1489210284Sjmallett cvmx_dprintf("ERROR:\n"); 1490210284Sjmallett cvmx_dprintf("ERROR: Board type is CVMX_BOARD_TYPE_CN3010_EVB_HS5, but Broadcom PHY found.\n"); 1491210284Sjmallett cvmx_dprintf("ERROR: The board type is mis-configured, and software malfunctions are likely.\n"); 1492210284Sjmallett cvmx_dprintf("ERROR: All boards require a unique board type to identify them.\n"); 1493210284Sjmallett cvmx_dprintf("ERROR:\n"); 1494210284Sjmallett cvmx_dprintf("\n"); 1495210284Sjmallett cvmx_wait(1000000000); 1496210284Sjmallett cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 5); 1497210284Sjmallett cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 5); 1498210284Sjmallett } 1499210284Sjmallett } 1500210284Sjmallett } 1501210284Sjmallett } 1502245712Sjmallett#if defined(OCTEON_VENDOR_UBIQUITI) 1503320073Sjhibbits else if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CUST_UBIQUITI_E100 || 1504320073Sjhibbits cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CUST_UBIQUITI_USG) 1505245712Sjmallett { 1506245712Sjmallett /* Configure ASX cloks for all ports on interface 0. */ 1507245712Sjmallett if (interface == 0) 1508245712Sjmallett { 1509245712Sjmallett int port; 1510245712Sjmallett 1511245712Sjmallett for (port = 0; port < 3; port++) { 1512245712Sjmallett cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface), 16); 1513245712Sjmallett cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, interface), 0); 1514245712Sjmallett } 1515245712Sjmallett } 1516245712Sjmallett } 1517245712Sjmallett#endif 1518210284Sjmallett return 0; 1519210284Sjmallett} 1520210284Sjmallett 1521215990Sjmallett 1522215990Sjmallett/** 1523215990Sjmallett * @INTERNAL 1524215990Sjmallett * Gets the clock type used for the USB block based on board type. 1525215990Sjmallett * Used by the USB code for auto configuration of clock type. 1526215990Sjmallett * 1527215990Sjmallett * @return USB clock type enumeration 1528215990Sjmallett */ 1529210284Sjmallettcvmx_helper_board_usb_clock_types_t __cvmx_helper_board_usb_get_clock_type(void) 1530210284Sjmallett{ 1531232812Sjmallett#if !defined(CVMX_BUILD_FOR_LINUX_KERNEL) && (!defined(__FreeBSD__) || !defined(_KERNEL)) 1532232812Sjmallett const void *fdt_addr = CASTPTR(const void *, cvmx_sysinfo_get()->fdt_addr); 1533232812Sjmallett int nodeoffset; 1534232812Sjmallett const void *nodep; 1535232812Sjmallett int len; 1536232812Sjmallett uint32_t speed = 0; 1537232812Sjmallett const char *type = NULL; 1538232812Sjmallett 1539232812Sjmallett if (fdt_addr) 1540232812Sjmallett { 1541232812Sjmallett nodeoffset = fdt_path_offset(fdt_addr, "/soc/uctl"); 1542232812Sjmallett if (nodeoffset < 0) 1543232812Sjmallett nodeoffset = fdt_path_offset(fdt_addr, "/soc/usbn"); 1544232812Sjmallett 1545232812Sjmallett if (nodeoffset >= 0) 1546232812Sjmallett { 1547232812Sjmallett nodep = fdt_getprop(fdt_addr, nodeoffset, "refclk-type", &len); 1548232812Sjmallett if (nodep != NULL && len > 0) 1549232812Sjmallett type = (const char *)nodep; 1550232812Sjmallett else 1551232812Sjmallett type = "unknown"; 1552232812Sjmallett nodep = fdt_getprop(fdt_addr, nodeoffset, "refclk-frequency", &len); 1553232812Sjmallett if (nodep != NULL && len == sizeof(uint32_t)) 1554232812Sjmallett speed = fdt32_to_cpu(*(int *)nodep); 1555232812Sjmallett else 1556232812Sjmallett speed = 0; 1557232812Sjmallett if (!strcmp(type, "crystal")) 1558232812Sjmallett { 1559232812Sjmallett if (speed == 0 || speed == 12000000) 1560232812Sjmallett return USB_CLOCK_TYPE_CRYSTAL_12; 1561232812Sjmallett else 1562232812Sjmallett printf("Warning: invalid crystal speed for USB clock type in FDT\n"); 1563232812Sjmallett } 1564232812Sjmallett else if (!strcmp(type, "external")) 1565232812Sjmallett { 1566232812Sjmallett switch (speed) { 1567232812Sjmallett case 12000000: 1568232812Sjmallett return USB_CLOCK_TYPE_REF_12; 1569232812Sjmallett case 24000000: 1570232812Sjmallett return USB_CLOCK_TYPE_REF_24; 1571232812Sjmallett case 0: 1572232812Sjmallett case 48000000: 1573232812Sjmallett return USB_CLOCK_TYPE_REF_48; 1574232812Sjmallett default: 1575232812Sjmallett printf("Warning: invalid USB clock speed of %u hz in FDT\n", speed); 1576232812Sjmallett } 1577232812Sjmallett } 1578232812Sjmallett else 1579232812Sjmallett printf("Warning: invalid USB reference clock type \"%s\" in FDT\n", type ? type : "NULL"); 1580232812Sjmallett } 1581232812Sjmallett } 1582232812Sjmallett#endif 1583215990Sjmallett switch (cvmx_sysinfo_get()->board_type) 1584215990Sjmallett { 1585215990Sjmallett case CVMX_BOARD_TYPE_BBGW_REF: 1586215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_A: 1587215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_U: 1588215990Sjmallett case CVMX_BOARD_TYPE_LANAI2_G: 1589210311Sjmallett#if defined(OCTEON_VENDOR_LANNER) 1590250428Simp case CVMX_BOARD_TYPE_CUST_LANNER_MR320: 1591250428Simp case CVMX_BOARD_TYPE_CUST_LANNER_MR321X: 1592210311Sjmallett#endif 1593244985Sjmallett#if defined(OCTEON_VENDOR_UBIQUITI) 1594250428Simp case CVMX_BOARD_TYPE_CUST_UBIQUITI_E100: 1595320073Sjhibbits case CVMX_BOARD_TYPE_CUST_UBIQUITI_USG: 1596244985Sjmallett#endif 1597229070Sgonzo#if defined(OCTEON_BOARD_CAPK_0100ND) 1598229070Sgonzo case CVMX_BOARD_TYPE_CN3010_EVB_HS5: 1599229070Sgonzo#endif 1600250428Simp#if defined(OCTEON_VENDOR_GEFES) /* All GEFES' boards use same xtal type */ 1601250428Simp case CVMX_BOARD_TYPE_TNPA3804: 1602250428Simp case CVMX_BOARD_TYPE_AT5810: 1603250428Simp case CVMX_BOARD_TYPE_WNPA3850: 1604250428Simp case CVMX_BOARD_TYPE_W3860: 1605250428Simp case CVMX_BOARD_TYPE_CUST_TNPA5804: 1606250428Simp case CVMX_BOARD_TYPE_CUST_W5434: 1607250428Simp case CVMX_BOARD_TYPE_CUST_W5650: 1608250428Simp case CVMX_BOARD_TYPE_CUST_W5800: 1609250428Simp case CVMX_BOARD_TYPE_CUST_W5651X: 1610250428Simp case CVMX_BOARD_TYPE_CUST_TNPA5651X: 1611250428Simp case CVMX_BOARD_TYPE_CUST_TNPA56X4: 1612250428Simp case CVMX_BOARD_TYPE_CUST_W63XX: 1613250428Simp#endif 1614232812Sjmallett case CVMX_BOARD_TYPE_NIC10E_66: 1615210284Sjmallett return USB_CLOCK_TYPE_CRYSTAL_12; 1616232812Sjmallett case CVMX_BOARD_TYPE_NIC10E: 1617232812Sjmallett return USB_CLOCK_TYPE_REF_12; 1618232812Sjmallett default: 1619232812Sjmallett break; 1620210284Sjmallett } 1621232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN6XXX) /* Most boards except NIC10e use a 12MHz crystal */ 1622232812Sjmallett || OCTEON_IS_MODEL(OCTEON_CNF7XXX)) 1623232812Sjmallett return USB_CLOCK_TYPE_CRYSTAL_12; 1624210284Sjmallett return USB_CLOCK_TYPE_REF_48; 1625210284Sjmallett} 1626210284Sjmallett 1627215990Sjmallett 1628215990Sjmallett/** 1629215990Sjmallett * @INTERNAL 1630215990Sjmallett * Adjusts the number of available USB ports on Octeon based on board 1631215990Sjmallett * specifics. 1632215990Sjmallett * 1633215990Sjmallett * @param supported_ports expected number of ports based on chip type; 1634215990Sjmallett * 1635215990Sjmallett * 1636215990Sjmallett * @return number of available usb ports, based on board specifics. 1637215990Sjmallett * Return value is supported_ports if function does not 1638215990Sjmallett * override. 1639215990Sjmallett */ 1640210284Sjmallettint __cvmx_helper_board_usb_get_num_ports(int supported_ports) 1641210284Sjmallett{ 1642215990Sjmallett switch (cvmx_sysinfo_get()->board_type) 1643215990Sjmallett { 1644210284Sjmallett case CVMX_BOARD_TYPE_NIC_XLE_4G: 1645232812Sjmallett case CVMX_BOARD_TYPE_NIC2E: 1646210284Sjmallett return 0; 1647210284Sjmallett } 1648210284Sjmallett 1649210284Sjmallett return supported_ports; 1650210284Sjmallett} 1651210284Sjmallett 1652210284Sjmallett 1653