162306a36Sopenharmony_ci/***********************license start*************** 262306a36Sopenharmony_ci * Author: Cavium Networks 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Contact: support@caviumnetworks.com 562306a36Sopenharmony_ci * This file is part of the OCTEON SDK 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (c) 2003-2008 Cavium Networks 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * This file is free software; you can redistribute it and/or modify 1062306a36Sopenharmony_ci * it under the terms of the GNU General Public License, Version 2, as 1162306a36Sopenharmony_ci * published by the Free Software Foundation. 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * This file is distributed in the hope that it will be useful, but 1462306a36Sopenharmony_ci * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 1562306a36Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 1662306a36Sopenharmony_ci * NONINFRINGEMENT. See the GNU General Public License for more 1762306a36Sopenharmony_ci * details. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * You should have received a copy of the GNU General Public License 2062306a36Sopenharmony_ci * along with this file; if not, write to the Free Software 2162306a36Sopenharmony_ci * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 2262306a36Sopenharmony_ci * or visit http://www.gnu.org/licenses/. 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * This file may also be available under a different license from Cavium. 2562306a36Sopenharmony_ci * Contact Cavium Networks for more information 2662306a36Sopenharmony_ci ***********************license end**************************************/ 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci/* 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * Helper functions to abstract board specific data about 3162306a36Sopenharmony_ci * network ports from the rest of the cvmx-helper files. 3262306a36Sopenharmony_ci */ 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#include <linux/bug.h> 3562306a36Sopenharmony_ci#include <asm/octeon/octeon.h> 3662306a36Sopenharmony_ci#include <asm/octeon/cvmx-bootinfo.h> 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#include <asm/octeon/cvmx-config.h> 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#include <asm/octeon/cvmx-helper.h> 4162306a36Sopenharmony_ci#include <asm/octeon/cvmx-helper-util.h> 4262306a36Sopenharmony_ci#include <asm/octeon/cvmx-helper-board.h> 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#include <asm/octeon/cvmx-gmxx-defs.h> 4562306a36Sopenharmony_ci#include <asm/octeon/cvmx-asxx-defs.h> 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci/* 4862306a36Sopenharmony_ci * Return the MII PHY address associated with the given IPD 4962306a36Sopenharmony_ci * port. A result of -1 means there isn't a MII capable PHY 5062306a36Sopenharmony_ci * connected to this port. On chips supporting multiple MII 5162306a36Sopenharmony_ci * busses the bus number is encoded in bits <15:8>. 5262306a36Sopenharmony_ci * 5362306a36Sopenharmony_ci * This function must be modified for every new Octeon board. 5462306a36Sopenharmony_ci * Internally it uses switch statements based on the cvmx_sysinfo 5562306a36Sopenharmony_ci * data to determine board types and revisions. It replies on the 5662306a36Sopenharmony_ci * fact that every Octeon board receives a unique board type 5762306a36Sopenharmony_ci * enumeration from the bootloader. 5862306a36Sopenharmony_ci * 5962306a36Sopenharmony_ci * @ipd_port: Octeon IPD port to get the MII address for. 6062306a36Sopenharmony_ci * 6162306a36Sopenharmony_ci * Returns MII PHY address and bus number or -1. 6262306a36Sopenharmony_ci */ 6362306a36Sopenharmony_ciint cvmx_helper_board_get_mii_address(int ipd_port) 6462306a36Sopenharmony_ci{ 6562306a36Sopenharmony_ci switch (cvmx_sysinfo_get()->board_type) { 6662306a36Sopenharmony_ci case CVMX_BOARD_TYPE_SIM: 6762306a36Sopenharmony_ci /* Simulator doesn't have MII */ 6862306a36Sopenharmony_ci return -1; 6962306a36Sopenharmony_ci case CVMX_BOARD_TYPE_EBT3000: 7062306a36Sopenharmony_ci case CVMX_BOARD_TYPE_EBT5800: 7162306a36Sopenharmony_ci case CVMX_BOARD_TYPE_THUNDER: 7262306a36Sopenharmony_ci case CVMX_BOARD_TYPE_NICPRO2: 7362306a36Sopenharmony_ci /* Interface 0 is SPI4, interface 1 is RGMII */ 7462306a36Sopenharmony_ci if ((ipd_port >= 16) && (ipd_port < 20)) 7562306a36Sopenharmony_ci return ipd_port - 16; 7662306a36Sopenharmony_ci else 7762306a36Sopenharmony_ci return -1; 7862306a36Sopenharmony_ci case CVMX_BOARD_TYPE_KODAMA: 7962306a36Sopenharmony_ci case CVMX_BOARD_TYPE_EBH3100: 8062306a36Sopenharmony_ci case CVMX_BOARD_TYPE_HIKARI: 8162306a36Sopenharmony_ci case CVMX_BOARD_TYPE_CN3010_EVB_HS5: 8262306a36Sopenharmony_ci case CVMX_BOARD_TYPE_CN3005_EVB_HS5: 8362306a36Sopenharmony_ci case CVMX_BOARD_TYPE_CN3020_EVB_HS5: 8462306a36Sopenharmony_ci /* 8562306a36Sopenharmony_ci * Port 0 is WAN connected to a PHY, Port 1 is GMII 8662306a36Sopenharmony_ci * connected to a switch 8762306a36Sopenharmony_ci */ 8862306a36Sopenharmony_ci if (ipd_port == 0) 8962306a36Sopenharmony_ci return 4; 9062306a36Sopenharmony_ci else if (ipd_port == 1) 9162306a36Sopenharmony_ci return 9; 9262306a36Sopenharmony_ci else 9362306a36Sopenharmony_ci return -1; 9462306a36Sopenharmony_ci case CVMX_BOARD_TYPE_NAC38: 9562306a36Sopenharmony_ci /* Board has 8 RGMII ports PHYs are 0-7 */ 9662306a36Sopenharmony_ci if ((ipd_port >= 0) && (ipd_port < 4)) 9762306a36Sopenharmony_ci return ipd_port; 9862306a36Sopenharmony_ci else if ((ipd_port >= 16) && (ipd_port < 20)) 9962306a36Sopenharmony_ci return ipd_port - 16 + 4; 10062306a36Sopenharmony_ci else 10162306a36Sopenharmony_ci return -1; 10262306a36Sopenharmony_ci case CVMX_BOARD_TYPE_EBH3000: 10362306a36Sopenharmony_ci /* Board has dual SPI4 and no PHYs */ 10462306a36Sopenharmony_ci return -1; 10562306a36Sopenharmony_ci case CVMX_BOARD_TYPE_EBH5200: 10662306a36Sopenharmony_ci case CVMX_BOARD_TYPE_EBH5201: 10762306a36Sopenharmony_ci case CVMX_BOARD_TYPE_EBT5200: 10862306a36Sopenharmony_ci /* Board has 2 management ports */ 10962306a36Sopenharmony_ci if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && 11062306a36Sopenharmony_ci (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2))) 11162306a36Sopenharmony_ci return ipd_port - CVMX_HELPER_BOARD_MGMT_IPD_PORT; 11262306a36Sopenharmony_ci /* 11362306a36Sopenharmony_ci * Board has 4 SGMII ports. The PHYs start right after the MII 11462306a36Sopenharmony_ci * ports MII0 = 0, MII1 = 1, SGMII = 2-5. 11562306a36Sopenharmony_ci */ 11662306a36Sopenharmony_ci if ((ipd_port >= 0) && (ipd_port < 4)) 11762306a36Sopenharmony_ci return ipd_port + 2; 11862306a36Sopenharmony_ci else 11962306a36Sopenharmony_ci return -1; 12062306a36Sopenharmony_ci case CVMX_BOARD_TYPE_EBH5600: 12162306a36Sopenharmony_ci case CVMX_BOARD_TYPE_EBH5601: 12262306a36Sopenharmony_ci case CVMX_BOARD_TYPE_EBH5610: 12362306a36Sopenharmony_ci /* Board has 1 management port */ 12462306a36Sopenharmony_ci if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT) 12562306a36Sopenharmony_ci return 0; 12662306a36Sopenharmony_ci /* 12762306a36Sopenharmony_ci * Board has 8 SGMII ports. 4 connect out, two connect 12862306a36Sopenharmony_ci * to a switch, and 2 loop to each other 12962306a36Sopenharmony_ci */ 13062306a36Sopenharmony_ci if ((ipd_port >= 0) && (ipd_port < 4)) 13162306a36Sopenharmony_ci return ipd_port + 1; 13262306a36Sopenharmony_ci else 13362306a36Sopenharmony_ci return -1; 13462306a36Sopenharmony_ci case CVMX_BOARD_TYPE_CUST_NB5: 13562306a36Sopenharmony_ci if (ipd_port == 2) 13662306a36Sopenharmony_ci return 4; 13762306a36Sopenharmony_ci else 13862306a36Sopenharmony_ci return -1; 13962306a36Sopenharmony_ci case CVMX_BOARD_TYPE_NIC_XLE_4G: 14062306a36Sopenharmony_ci /* Board has 4 SGMII ports. connected QLM3(interface 1) */ 14162306a36Sopenharmony_ci if ((ipd_port >= 16) && (ipd_port < 20)) 14262306a36Sopenharmony_ci return ipd_port - 16 + 1; 14362306a36Sopenharmony_ci else 14462306a36Sopenharmony_ci return -1; 14562306a36Sopenharmony_ci case CVMX_BOARD_TYPE_NIC_XLE_10G: 14662306a36Sopenharmony_ci case CVMX_BOARD_TYPE_NIC10E: 14762306a36Sopenharmony_ci return -1; 14862306a36Sopenharmony_ci case CVMX_BOARD_TYPE_NIC4E: 14962306a36Sopenharmony_ci if (ipd_port >= 0 && ipd_port <= 3) 15062306a36Sopenharmony_ci return (ipd_port + 0x1f) & 0x1f; 15162306a36Sopenharmony_ci else 15262306a36Sopenharmony_ci return -1; 15362306a36Sopenharmony_ci case CVMX_BOARD_TYPE_NIC2E: 15462306a36Sopenharmony_ci if (ipd_port >= 0 && ipd_port <= 1) 15562306a36Sopenharmony_ci return ipd_port + 1; 15662306a36Sopenharmony_ci else 15762306a36Sopenharmony_ci return -1; 15862306a36Sopenharmony_ci case CVMX_BOARD_TYPE_BBGW_REF: 15962306a36Sopenharmony_ci /* 16062306a36Sopenharmony_ci * No PHYs are connected to Octeon, everything is 16162306a36Sopenharmony_ci * through switch. 16262306a36Sopenharmony_ci */ 16362306a36Sopenharmony_ci return -1; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci case CVMX_BOARD_TYPE_CUST_WSX16: 16662306a36Sopenharmony_ci if (ipd_port >= 0 && ipd_port <= 3) 16762306a36Sopenharmony_ci return ipd_port; 16862306a36Sopenharmony_ci else if (ipd_port >= 16 && ipd_port <= 19) 16962306a36Sopenharmony_ci return ipd_port - 16 + 4; 17062306a36Sopenharmony_ci else 17162306a36Sopenharmony_ci return -1; 17262306a36Sopenharmony_ci case CVMX_BOARD_TYPE_UBNT_E100: 17362306a36Sopenharmony_ci if (ipd_port >= 0 && ipd_port <= 2) 17462306a36Sopenharmony_ci return 7 - ipd_port; 17562306a36Sopenharmony_ci else 17662306a36Sopenharmony_ci return -1; 17762306a36Sopenharmony_ci case CVMX_BOARD_TYPE_KONTRON_S1901: 17862306a36Sopenharmony_ci if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT) 17962306a36Sopenharmony_ci return 1; 18062306a36Sopenharmony_ci else 18162306a36Sopenharmony_ci return -1; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci } 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci /* Some unknown board. Somebody forgot to update this function... */ 18662306a36Sopenharmony_ci cvmx_dprintf 18762306a36Sopenharmony_ci ("cvmx_helper_board_get_mii_address: Unknown board type %d\n", 18862306a36Sopenharmony_ci cvmx_sysinfo_get()->board_type); 18962306a36Sopenharmony_ci return -1; 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci/* 19362306a36Sopenharmony_ci * This function is the board specific method of determining an 19462306a36Sopenharmony_ci * ethernet ports link speed. Most Octeon boards have Marvell PHYs 19562306a36Sopenharmony_ci * and are handled by the fall through case. This function must be 19662306a36Sopenharmony_ci * updated for boards that don't have the normal Marvell PHYs. 19762306a36Sopenharmony_ci * 19862306a36Sopenharmony_ci * This function must be modified for every new Octeon board. 19962306a36Sopenharmony_ci * Internally it uses switch statements based on the cvmx_sysinfo 20062306a36Sopenharmony_ci * data to determine board types and revisions. It relies on the 20162306a36Sopenharmony_ci * fact that every Octeon board receives a unique board type 20262306a36Sopenharmony_ci * enumeration from the bootloader. 20362306a36Sopenharmony_ci * 20462306a36Sopenharmony_ci * @ipd_port: IPD input port associated with the port we want to get link 20562306a36Sopenharmony_ci * status for. 20662306a36Sopenharmony_ci * 20762306a36Sopenharmony_ci * Returns The ports link status. If the link isn't fully resolved, this must 20862306a36Sopenharmony_ci * return zero. 20962306a36Sopenharmony_ci */ 21062306a36Sopenharmony_ciunion cvmx_helper_link_info __cvmx_helper_board_link_get(int ipd_port) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci union cvmx_helper_link_info result; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci WARN_ONCE(!octeon_is_simulation(), 21562306a36Sopenharmony_ci "Using deprecated link status - please update your DT"); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci /* Unless we fix it later, all links are defaulted to down */ 21862306a36Sopenharmony_ci result.u64 = 0; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci if (octeon_is_simulation()) { 22162306a36Sopenharmony_ci /* The simulator gives you a simulated 1Gbps full duplex link */ 22262306a36Sopenharmony_ci result.s.link_up = 1; 22362306a36Sopenharmony_ci result.s.full_duplex = 1; 22462306a36Sopenharmony_ci result.s.speed = 1000; 22562306a36Sopenharmony_ci return result; 22662306a36Sopenharmony_ci } 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci if (OCTEON_IS_MODEL(OCTEON_CN3XXX) 22962306a36Sopenharmony_ci || OCTEON_IS_MODEL(OCTEON_CN58XX) 23062306a36Sopenharmony_ci || OCTEON_IS_MODEL(OCTEON_CN50XX)) { 23162306a36Sopenharmony_ci /* 23262306a36Sopenharmony_ci * We don't have a PHY address, so attempt to use 23362306a36Sopenharmony_ci * in-band status. It is really important that boards 23462306a36Sopenharmony_ci * not supporting in-band status never get 23562306a36Sopenharmony_ci * here. Reading broken in-band status tends to do bad 23662306a36Sopenharmony_ci * things 23762306a36Sopenharmony_ci */ 23862306a36Sopenharmony_ci union cvmx_gmxx_rxx_rx_inbnd inband_status; 23962306a36Sopenharmony_ci int interface = cvmx_helper_get_interface_num(ipd_port); 24062306a36Sopenharmony_ci int index = cvmx_helper_get_interface_index_num(ipd_port); 24162306a36Sopenharmony_ci inband_status.u64 = 24262306a36Sopenharmony_ci cvmx_read_csr(CVMX_GMXX_RXX_RX_INBND(index, interface)); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci result.s.link_up = inband_status.s.status; 24562306a36Sopenharmony_ci result.s.full_duplex = inband_status.s.duplex; 24662306a36Sopenharmony_ci switch (inband_status.s.speed) { 24762306a36Sopenharmony_ci case 0: /* 10 Mbps */ 24862306a36Sopenharmony_ci result.s.speed = 10; 24962306a36Sopenharmony_ci break; 25062306a36Sopenharmony_ci case 1: /* 100 Mbps */ 25162306a36Sopenharmony_ci result.s.speed = 100; 25262306a36Sopenharmony_ci break; 25362306a36Sopenharmony_ci case 2: /* 1 Gbps */ 25462306a36Sopenharmony_ci result.s.speed = 1000; 25562306a36Sopenharmony_ci break; 25662306a36Sopenharmony_ci case 3: /* Illegal */ 25762306a36Sopenharmony_ci result.u64 = 0; 25862306a36Sopenharmony_ci break; 25962306a36Sopenharmony_ci } 26062306a36Sopenharmony_ci } else { 26162306a36Sopenharmony_ci /* 26262306a36Sopenharmony_ci * We don't have a PHY address and we don't have 26362306a36Sopenharmony_ci * in-band status. There is no way to determine the 26462306a36Sopenharmony_ci * link speed. Return down assuming this port isn't 26562306a36Sopenharmony_ci * wired 26662306a36Sopenharmony_ci */ 26762306a36Sopenharmony_ci result.u64 = 0; 26862306a36Sopenharmony_ci } 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci /* If link is down, return all fields as zero. */ 27162306a36Sopenharmony_ci if (!result.s.link_up) 27262306a36Sopenharmony_ci result.u64 = 0; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci return result; 27562306a36Sopenharmony_ci} 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci/* 27862306a36Sopenharmony_ci * This function is called by cvmx_helper_interface_probe() after it 27962306a36Sopenharmony_ci * determines the number of ports Octeon can support on a specific 28062306a36Sopenharmony_ci * interface. This function is the per board location to override 28162306a36Sopenharmony_ci * this value. It is called with the number of ports Octeon might 28262306a36Sopenharmony_ci * support and should return the number of actual ports on the 28362306a36Sopenharmony_ci * board. 28462306a36Sopenharmony_ci * 28562306a36Sopenharmony_ci * This function must be modified for every new Octeon board. 28662306a36Sopenharmony_ci * Internally it uses switch statements based on the cvmx_sysinfo 28762306a36Sopenharmony_ci * data to determine board types and revisions. It relies on the 28862306a36Sopenharmony_ci * fact that every Octeon board receives a unique board type 28962306a36Sopenharmony_ci * enumeration from the bootloader. 29062306a36Sopenharmony_ci * 29162306a36Sopenharmony_ci * @interface: Interface to probe 29262306a36Sopenharmony_ci * @supported_ports: 29362306a36Sopenharmony_ci * Number of ports Octeon supports. 29462306a36Sopenharmony_ci * 29562306a36Sopenharmony_ci * Returns Number of ports the actual board supports. Many times this will 29662306a36Sopenharmony_ci * simple be "support_ports". 29762306a36Sopenharmony_ci */ 29862306a36Sopenharmony_ciint __cvmx_helper_board_interface_probe(int interface, int supported_ports) 29962306a36Sopenharmony_ci{ 30062306a36Sopenharmony_ci switch (cvmx_sysinfo_get()->board_type) { 30162306a36Sopenharmony_ci case CVMX_BOARD_TYPE_CN3005_EVB_HS5: 30262306a36Sopenharmony_ci if (interface == 0) 30362306a36Sopenharmony_ci return 2; 30462306a36Sopenharmony_ci break; 30562306a36Sopenharmony_ci case CVMX_BOARD_TYPE_BBGW_REF: 30662306a36Sopenharmony_ci if (interface == 0) 30762306a36Sopenharmony_ci return 2; 30862306a36Sopenharmony_ci break; 30962306a36Sopenharmony_ci case CVMX_BOARD_TYPE_NIC_XLE_4G: 31062306a36Sopenharmony_ci if (interface == 0) 31162306a36Sopenharmony_ci return 0; 31262306a36Sopenharmony_ci break; 31362306a36Sopenharmony_ci /* The 2nd interface on the EBH5600 is connected to the Marvel switch, 31462306a36Sopenharmony_ci which we don't support. Disable ports connected to it */ 31562306a36Sopenharmony_ci case CVMX_BOARD_TYPE_EBH5600: 31662306a36Sopenharmony_ci if (interface == 1) 31762306a36Sopenharmony_ci return 0; 31862306a36Sopenharmony_ci break; 31962306a36Sopenharmony_ci } 32062306a36Sopenharmony_ci return supported_ports; 32162306a36Sopenharmony_ci} 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci/* 32462306a36Sopenharmony_ci * Get the clock type used for the USB block based on board type. 32562306a36Sopenharmony_ci * Used by the USB code for auto configuration of clock type. 32662306a36Sopenharmony_ci * 32762306a36Sopenharmony_ci * Return USB clock type enumeration 32862306a36Sopenharmony_ci */ 32962306a36Sopenharmony_cienum cvmx_helper_board_usb_clock_types __cvmx_helper_board_usb_get_clock_type(void) 33062306a36Sopenharmony_ci{ 33162306a36Sopenharmony_ci switch (cvmx_sysinfo_get()->board_type) { 33262306a36Sopenharmony_ci case CVMX_BOARD_TYPE_BBGW_REF: 33362306a36Sopenharmony_ci case CVMX_BOARD_TYPE_LANAI2_A: 33462306a36Sopenharmony_ci case CVMX_BOARD_TYPE_LANAI2_U: 33562306a36Sopenharmony_ci case CVMX_BOARD_TYPE_LANAI2_G: 33662306a36Sopenharmony_ci case CVMX_BOARD_TYPE_NIC10E_66: 33762306a36Sopenharmony_ci case CVMX_BOARD_TYPE_UBNT_E100: 33862306a36Sopenharmony_ci return USB_CLOCK_TYPE_CRYSTAL_12; 33962306a36Sopenharmony_ci case CVMX_BOARD_TYPE_NIC10E: 34062306a36Sopenharmony_ci return USB_CLOCK_TYPE_REF_12; 34162306a36Sopenharmony_ci default: 34262306a36Sopenharmony_ci break; 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci /* Most boards except NIC10e use a 12MHz crystal */ 34562306a36Sopenharmony_ci if (OCTEON_IS_OCTEON2()) 34662306a36Sopenharmony_ci return USB_CLOCK_TYPE_CRYSTAL_12; 34762306a36Sopenharmony_ci return USB_CLOCK_TYPE_REF_48; 34862306a36Sopenharmony_ci} 349