2009-05-05 17:35:21 -07:00
/***********************license start***************
* Author : Cavium Networks
*
* Contact : support @ caviumnetworks . com
* This file is part of the OCTEON SDK
*
* Copyright ( c ) 2003 - 2008 Cavium Networks
*
* This file is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License , Version 2 , as
* published by the Free Software Foundation .
*
* This file is distributed in the hope that it will be useful , but
* AS - IS and WITHOUT ANY WARRANTY ; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE , TITLE , or
* NONINFRINGEMENT . See the GNU General Public License for more
* details .
*
* You should have received a copy of the GNU General Public License
* along with this file ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
* or visit http : //www.gnu.org/licenses/.
*
* This file may also be available under a different license from Cavium .
* Contact Cavium Networks for more information
* * * * * * * * * * * * * * * * * * * * * * * license end * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
*
* Helper functions to abstract board specific data about
* network ports from the rest of the cvmx - helper files .
*/
# include <asm/octeon/octeon.h>
# include <asm/octeon/cvmx-bootinfo.h>
2011-11-22 14:47:00 +00:00
# include <asm/octeon/cvmx-config.h>
2009-05-05 17:35:21 -07:00
2011-11-22 14:47:00 +00:00
# include <asm/octeon/cvmx-helper.h>
# include <asm/octeon/cvmx-helper-util.h>
# include <asm/octeon/cvmx-helper-board.h>
2009-05-05 17:35:21 -07:00
2011-11-22 14:47:00 +00:00
# include <asm/octeon/cvmx-gmxx-defs.h>
# include <asm/octeon/cvmx-asxx-defs.h>
2009-05-05 17:35:21 -07:00
/**
* Return the MII PHY address associated with the given IPD
* port . A result of - 1 means there isn ' t a MII capable PHY
* connected to this port . On chips supporting multiple MII
* busses the bus number is encoded in bits < 15 : 8 > .
*
* This function must be modified for every new Octeon board .
* Internally it uses switch statements based on the cvmx_sysinfo
* data to determine board types and revisions . It replies on the
* fact that every Octeon board receives a unique board type
* enumeration from the bootloader .
*
* @ ipd_port : Octeon IPD port to get the MII address for .
*
* Returns MII PHY address and bus number or - 1.
*/
int cvmx_helper_board_get_mii_address ( int ipd_port )
{
switch ( cvmx_sysinfo_get ( ) - > board_type ) {
case CVMX_BOARD_TYPE_SIM :
/* Simulator doesn't have MII */
return - 1 ;
case CVMX_BOARD_TYPE_EBT3000 :
case CVMX_BOARD_TYPE_EBT5800 :
case CVMX_BOARD_TYPE_THUNDER :
case CVMX_BOARD_TYPE_NICPRO2 :
/* Interface 0 is SPI4, interface 1 is RGMII */
if ( ( ipd_port > = 16 ) & & ( ipd_port < 20 ) )
return ipd_port - 16 ;
else
return - 1 ;
case CVMX_BOARD_TYPE_KODAMA :
case CVMX_BOARD_TYPE_EBH3100 :
case CVMX_BOARD_TYPE_HIKARI :
case CVMX_BOARD_TYPE_CN3010_EVB_HS5 :
case CVMX_BOARD_TYPE_CN3005_EVB_HS5 :
case CVMX_BOARD_TYPE_CN3020_EVB_HS5 :
/*
* Port 0 is WAN connected to a PHY , Port 1 is GMII
* connected to a switch
*/
if ( ipd_port = = 0 )
return 4 ;
else if ( ipd_port = = 1 )
return 9 ;
else
return - 1 ;
case CVMX_BOARD_TYPE_NAC38 :
/* Board has 8 RGMII ports PHYs are 0-7 */
if ( ( ipd_port > = 0 ) & & ( ipd_port < 4 ) )
return ipd_port ;
else if ( ( ipd_port > = 16 ) & & ( ipd_port < 20 ) )
return ipd_port - 16 + 4 ;
else
return - 1 ;
case CVMX_BOARD_TYPE_EBH3000 :
/* Board has dual SPI4 and no PHYs */
return - 1 ;
case CVMX_BOARD_TYPE_EBH5200 :
case CVMX_BOARD_TYPE_EBH5201 :
case CVMX_BOARD_TYPE_EBT5200 :
2011-11-22 14:47:03 +00:00
/* Board has 2 management ports */
if ( ( ipd_port > = CVMX_HELPER_BOARD_MGMT_IPD_PORT ) & &
( ipd_port < ( CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2 ) ) )
return ipd_port - CVMX_HELPER_BOARD_MGMT_IPD_PORT ;
2009-05-05 17:35:21 -07:00
/*
* Board has 4 SGMII ports . The PHYs start right after the MII
* ports MII0 = 0 , MII1 = 1 , SGMII = 2 - 5.
*/
if ( ( ipd_port > = 0 ) & & ( ipd_port < 4 ) )
return ipd_port + 2 ;
else
return - 1 ;
case CVMX_BOARD_TYPE_EBH5600 :
case CVMX_BOARD_TYPE_EBH5601 :
case CVMX_BOARD_TYPE_EBH5610 :
2011-11-22 14:47:03 +00:00
/* Board has 1 management port */
if ( ipd_port = = CVMX_HELPER_BOARD_MGMT_IPD_PORT )
return 0 ;
2009-05-05 17:35:21 -07:00
/*
* Board has 8 SGMII ports . 4 connect out , two connect
* to a switch , and 2 loop to each other
*/
if ( ( ipd_port > = 0 ) & & ( ipd_port < 4 ) )
return ipd_port + 1 ;
else
return - 1 ;
case CVMX_BOARD_TYPE_CUST_NB5 :
if ( ipd_port = = 2 )
return 4 ;
else
return - 1 ;
case CVMX_BOARD_TYPE_NIC_XLE_4G :
/* Board has 4 SGMII ports. connected QLM3(interface 1) */
if ( ( ipd_port > = 16 ) & & ( ipd_port < 20 ) )
return ipd_port - 16 + 1 ;
else
return - 1 ;
2011-11-22 14:47:03 +00:00
case CVMX_BOARD_TYPE_NIC_XLE_10G :
case CVMX_BOARD_TYPE_NIC10E :
return - 1 ;
case CVMX_BOARD_TYPE_NIC4E :
if ( ipd_port > = 0 & & ipd_port < = 3 )
return ( ipd_port + 0x1f ) & 0x1f ;
else
return - 1 ;
case CVMX_BOARD_TYPE_NIC2E :
if ( ipd_port > = 0 & & ipd_port < = 1 )
return ipd_port + 1 ;
else
return - 1 ;
2009-05-05 17:35:21 -07:00
case CVMX_BOARD_TYPE_BBGW_REF :
/*
* No PHYs are connected to Octeon , everything is
* through switch .
*/
return - 1 ;
2010-04-01 18:17:55 -07:00
case CVMX_BOARD_TYPE_CUST_WSX16 :
if ( ipd_port > = 0 & & ipd_port < = 3 )
return ipd_port ;
else if ( ipd_port > = 16 & & ipd_port < = 19 )
return ipd_port - 16 + 4 ;
else
return - 1 ;
2013-06-23 20:38:44 +00:00
case CVMX_BOARD_TYPE_UBNT_E100 :
if ( ipd_port > = 0 & & ipd_port < = 2 )
return 7 - ipd_port ;
else
return - 1 ;
2015-08-11 10:56:28 +03:00
case CVMX_BOARD_TYPE_KONTRON_S1901 :
if ( ipd_port = = CVMX_HELPER_BOARD_MGMT_IPD_PORT )
return 1 ;
else
return - 1 ;
2009-05-05 17:35:21 -07:00
}
/* Some unknown board. Somebody forgot to update this function... */
cvmx_dprintf
( " cvmx_helper_board_get_mii_address: Unknown board type %d \n " ,
cvmx_sysinfo_get ( ) - > board_type ) ;
return - 1 ;
}
/**
* This function is the board specific method of determining an
* ethernet ports link speed . Most Octeon boards have Marvell PHYs
* and are handled by the fall through case . This function must be
* updated for boards that don ' t have the normal Marvell PHYs .
*
* This function must be modified for every new Octeon board .
* Internally it uses switch statements based on the cvmx_sysinfo
* data to determine board types and revisions . It relies on the
* fact that every Octeon board receives a unique board type
* enumeration from the bootloader .
*
* @ ipd_port : IPD input port associated with the port we want to get link
2013-01-22 12:59:30 +01:00
* status for .
2009-05-05 17:35:21 -07:00
*
* Returns The ports link status . If the link isn ' t fully resolved , this must
2013-01-22 12:59:30 +01:00
* return zero .
2009-05-05 17:35:21 -07:00
*/
cvmx_helper_link_info_t __cvmx_helper_board_link_get ( int ipd_port )
{
cvmx_helper_link_info_t result ;
/* Unless we fix it later, all links are defaulted to down */
result . u64 = 0 ;
/*
* This switch statement should handle all ports that either don ' t use
* Marvell PHYS , or don ' t support in - band status .
*/
switch ( cvmx_sysinfo_get ( ) - > board_type ) {
case CVMX_BOARD_TYPE_SIM :
/* The simulator gives you a simulated 1Gbps full duplex link */
result . s . link_up = 1 ;
result . s . full_duplex = 1 ;
result . s . speed = 1000 ;
return result ;
case CVMX_BOARD_TYPE_EBH3100 :
case CVMX_BOARD_TYPE_CN3010_EVB_HS5 :
case CVMX_BOARD_TYPE_CN3005_EVB_HS5 :
case CVMX_BOARD_TYPE_CN3020_EVB_HS5 :
/* Port 1 on these boards is always Gigabit */
if ( ipd_port = = 1 ) {
result . s . link_up = 1 ;
result . s . full_duplex = 1 ;
result . s . speed = 1000 ;
return result ;
}
/* Fall through to the generic code below */
break ;
case CVMX_BOARD_TYPE_CUST_NB5 :
/* Port 1 on these boards is always Gigabit */
if ( ipd_port = = 1 ) {
result . s . link_up = 1 ;
result . s . full_duplex = 1 ;
result . s . speed = 1000 ;
return result ;
2016-09-02 23:44:20 +03:00
}
2009-05-05 17:35:21 -07:00
break ;
case CVMX_BOARD_TYPE_BBGW_REF :
/* Port 1 on these boards is always Gigabit */
if ( ipd_port = = 2 ) {
/* Port 2 is not hooked up */
result . u64 = 0 ;
return result ;
} else {
/* Ports 0 and 1 connect to the switch */
result . s . link_up = 1 ;
result . s . full_duplex = 1 ;
result . s . speed = 1000 ;
return result ;
}
break ;
}
2016-09-02 23:44:20 +03:00
if ( OCTEON_IS_MODEL ( OCTEON_CN3XXX )
2009-05-05 17:35:21 -07:00
| | OCTEON_IS_MODEL ( OCTEON_CN58XX )
| | OCTEON_IS_MODEL ( OCTEON_CN50XX ) ) {
/*
* We don ' t have a PHY address , so attempt to use
* in - band status . It is really important that boards
* not supporting in - band status never get
* here . Reading broken in - band status tends to do bad
* things
*/
union cvmx_gmxx_rxx_rx_inbnd inband_status ;
int interface = cvmx_helper_get_interface_num ( ipd_port ) ;
int index = cvmx_helper_get_interface_index_num ( ipd_port ) ;
inband_status . u64 =
cvmx_read_csr ( CVMX_GMXX_RXX_RX_INBND ( index , interface ) ) ;
result . s . link_up = inband_status . s . status ;
result . s . full_duplex = inband_status . s . duplex ;
switch ( inband_status . s . speed ) {
2013-01-22 12:59:30 +01:00
case 0 : /* 10 Mbps */
2009-05-05 17:35:21 -07:00
result . s . speed = 10 ;
break ;
2013-01-22 12:59:30 +01:00
case 1 : /* 100 Mbps */
2009-05-05 17:35:21 -07:00
result . s . speed = 100 ;
break ;
2013-01-22 12:59:30 +01:00
case 2 : /* 1 Gbps */
2009-05-05 17:35:21 -07:00
result . s . speed = 1000 ;
break ;
2013-01-22 12:59:30 +01:00
case 3 : /* Illegal */
2009-05-05 17:35:21 -07:00
result . u64 = 0 ;
break ;
}
} else {
/*
* We don ' t have a PHY address and we don ' t have
* in - band status . There is no way to determine the
* link speed . Return down assuming this port isn ' t
* wired
*/
result . u64 = 0 ;
}
/* If link is down, return all fields as zero. */
if ( ! result . s . link_up )
result . u64 = 0 ;
return result ;
}
/**
* This function is called by cvmx_helper_interface_probe ( ) after it
* determines the number of ports Octeon can support on a specific
* interface . This function is the per board location to override
* this value . It is called with the number of ports Octeon might
* support and should return the number of actual ports on the
* board .
*
* This function must be modifed for every new Octeon board .
* Internally it uses switch statements based on the cvmx_sysinfo
* data to determine board types and revisions . It relys on the
* fact that every Octeon board receives a unique board type
* enumeration from the bootloader .
*
* @ interface : Interface to probe
* @ supported_ports :
2013-01-22 12:59:30 +01:00
* Number of ports Octeon supports .
2009-05-05 17:35:21 -07:00
*
* Returns Number of ports the actual board supports . Many times this will
2013-01-22 12:59:30 +01:00
* simple be " support_ports " .
2009-05-05 17:35:21 -07:00
*/
int __cvmx_helper_board_interface_probe ( int interface , int supported_ports )
{
switch ( cvmx_sysinfo_get ( ) - > board_type ) {
case CVMX_BOARD_TYPE_CN3005_EVB_HS5 :
if ( interface = = 0 )
return 2 ;
break ;
case CVMX_BOARD_TYPE_BBGW_REF :
if ( interface = = 0 )
return 2 ;
break ;
case CVMX_BOARD_TYPE_NIC_XLE_4G :
if ( interface = = 0 )
return 0 ;
break ;
/* The 2nd interface on the EBH5600 is connected to the Marvel switch,
which we don ' t support . Disable ports connected to it */
case CVMX_BOARD_TYPE_EBH5600 :
if ( interface = = 1 )
return 0 ;
break ;
}
return supported_ports ;
}
/**
* Enable packet input / output from the hardware . This function is
* called after by cvmx_helper_packet_hardware_enable ( ) to
* perform board specific initialization . For most boards
* nothing is needed .
*
* @ interface : Interface to enable
*
* Returns Zero on success , negative on failure
*/
int __cvmx_helper_board_hardware_enable ( int interface )
{
if ( cvmx_sysinfo_get ( ) - > board_type = = CVMX_BOARD_TYPE_CN3005_EVB_HS5 ) {
if ( interface = = 0 ) {
/* Different config for switch port */
cvmx_write_csr ( CVMX_ASXX_TX_CLK_SETX ( 1 , interface ) , 0 ) ;
cvmx_write_csr ( CVMX_ASXX_RX_CLK_SETX ( 1 , interface ) , 0 ) ;
/*
* Boards with gigabit WAN ports need a
* different setting that is compatible with
* 100 Mbit settings
*/
cvmx_write_csr ( CVMX_ASXX_TX_CLK_SETX ( 0 , interface ) ,
0xc ) ;
cvmx_write_csr ( CVMX_ASXX_RX_CLK_SETX ( 0 , interface ) ,
0xc ) ;
}
2013-06-23 20:38:44 +00:00
} else if ( cvmx_sysinfo_get ( ) - > board_type = =
CVMX_BOARD_TYPE_UBNT_E100 ) {
cvmx_write_csr ( CVMX_ASXX_RX_CLK_SETX ( 0 , interface ) , 0 ) ;
cvmx_write_csr ( CVMX_ASXX_TX_CLK_SETX ( 0 , interface ) , 0x10 ) ;
cvmx_write_csr ( CVMX_ASXX_RX_CLK_SETX ( 1 , interface ) , 0 ) ;
cvmx_write_csr ( CVMX_ASXX_TX_CLK_SETX ( 1 , interface ) , 0x10 ) ;
cvmx_write_csr ( CVMX_ASXX_RX_CLK_SETX ( 2 , interface ) , 0 ) ;
cvmx_write_csr ( CVMX_ASXX_TX_CLK_SETX ( 2 , interface ) , 0x10 ) ;
2009-05-05 17:35:21 -07:00
}
return 0 ;
}
2013-12-03 11:46:51 -08:00
/**
* Get the clock type used for the USB block based on board type .
* Used by the USB code for auto configuration of clock type .
*
* Return USB clock type enumeration
*/
enum cvmx_helper_board_usb_clock_types __cvmx_helper_board_usb_get_clock_type ( void )
{
switch ( cvmx_sysinfo_get ( ) - > board_type ) {
case CVMX_BOARD_TYPE_BBGW_REF :
case CVMX_BOARD_TYPE_LANAI2_A :
case CVMX_BOARD_TYPE_LANAI2_U :
case CVMX_BOARD_TYPE_LANAI2_G :
case CVMX_BOARD_TYPE_NIC10E_66 :
case CVMX_BOARD_TYPE_UBNT_E100 :
return USB_CLOCK_TYPE_CRYSTAL_12 ;
case CVMX_BOARD_TYPE_NIC10E :
return USB_CLOCK_TYPE_REF_12 ;
default :
break ;
}
/* Most boards except NIC10e use a 12MHz crystal */
2015-01-15 16:11:14 +03:00
if ( OCTEON_IS_OCTEON2 ( ) )
2013-12-03 11:46:51 -08:00
return USB_CLOCK_TYPE_CRYSTAL_12 ;
return USB_CLOCK_TYPE_REF_48 ;
}