@ -14,6 +14,7 @@
# include <errno.h>
# include <malloc.h>
# include <vsc9953.h>
# include <ethsw.h>
static struct vsc9953_info vsc9953_l2sw = {
. port [ 0 ] = VSC9953_PORT_INFO_INITIALIZER ( 0 ) ,
@ -405,6 +406,165 @@ static void vsc9953_port_all_vlan_egress_untagged_set(
vsc9953_port_vlan_egr_untag_set ( i , mode ) ;
}
# ifdef CONFIG_CMD_ETHSW
/* Enable/disable status of a VSC9953 port */
static void vsc9953_port_status_set ( int port_no , u8 enabled )
{
struct vsc9953_qsys_reg * l2qsys_reg ;
/* Administrative down */
if ( ! vsc9953_l2sw . port [ port_no ] . enabled )
return ;
l2qsys_reg = ( struct vsc9953_qsys_reg * ) ( VSC9953_OFFSET +
VSC9953_QSYS_OFFSET ) ;
if ( enabled )
setbits_le32 ( & l2qsys_reg - > sys . switch_port_mode [ port_no ] ,
VSC9953_PORT_ENA ) ;
else
clrbits_le32 ( & l2qsys_reg - > sys . switch_port_mode [ port_no ] ,
VSC9953_PORT_ENA ) ;
}
/* Start autonegotiation for a VSC9953 PHY */
static void vsc9953_phy_autoneg ( int port_no )
{
if ( ! vsc9953_l2sw . port [ port_no ] . phydev )
return ;
if ( vsc9953_l2sw . port [ port_no ] . phydev - > drv - > startup (
vsc9953_l2sw . port [ port_no ] . phydev ) )
printf ( " Failed to start PHY for port %d \n " , port_no ) ;
}
/* Print a VSC9953 port's configuration */
static void vsc9953_port_config_show ( int port_no )
{
int speed ;
int duplex ;
int link ;
u8 enabled ;
u32 val ;
struct vsc9953_qsys_reg * l2qsys_reg ;
l2qsys_reg = ( struct vsc9953_qsys_reg * ) ( VSC9953_OFFSET +
VSC9953_QSYS_OFFSET ) ;
val = in_le32 ( & l2qsys_reg - > sys . switch_port_mode [ port_no ] ) ;
enabled = vsc9953_l2sw . port [ port_no ] . enabled & &
( val & VSC9953_PORT_ENA ) ;
/* internal ports (8 and 9) are fixed */
if ( VSC9953_INTERNAL_PORT_CHECK ( port_no ) ) {
link = 1 ;
speed = SPEED_2500 ;
duplex = DUPLEX_FULL ;
} else {
if ( vsc9953_l2sw . port [ port_no ] . phydev ) {
link = vsc9953_l2sw . port [ port_no ] . phydev - > link ;
speed = vsc9953_l2sw . port [ port_no ] . phydev - > speed ;
duplex = vsc9953_l2sw . port [ port_no ] . phydev - > duplex ;
} else {
link = - 1 ;
speed = - 1 ;
duplex = - 1 ;
}
}
printf ( " %8d " , port_no ) ;
printf ( " %8s " , enabled = = 1 ? " enabled " : " disabled " ) ;
printf ( " %8s " , link = = 1 ? " up " : " down " ) ;
switch ( speed ) {
case SPEED_10 :
printf ( " %8d " , 10 ) ;
break ;
case SPEED_100 :
printf ( " %8d " , 100 ) ;
break ;
case SPEED_1000 :
printf ( " %8d " , 1000 ) ;
break ;
case SPEED_2500 :
printf ( " %8d " , 2500 ) ;
break ;
case SPEED_10000 :
printf ( " %8d " , 10000 ) ;
break ;
default :
printf ( " %8s " , " - " ) ;
}
printf ( " %8s \n " , duplex = = DUPLEX_FULL ? " full " : " half " ) ;
}
static int vsc9953_port_status_key_func ( struct ethsw_command_def * parsed_cmd )
{
int i ;
u8 enabled ;
/* Last keyword should tell us if we should enable/disable the port */
if ( parsed_cmd - > cmd_to_keywords [ parsed_cmd - > cmd_keywords_nr - 1 ] = =
ethsw_id_enable )
enabled = 1 ;
else if ( parsed_cmd - > cmd_to_keywords [ parsed_cmd - > cmd_keywords_nr - 1 ] = =
ethsw_id_disable )
enabled = 0 ;
else
return CMD_RET_USAGE ;
if ( parsed_cmd - > port ! = ETHSW_CMD_PORT_ALL ) {
if ( ! VSC9953_PORT_CHECK ( parsed_cmd - > port ) ) {
printf ( " Invalid port number: %d \n " , parsed_cmd - > port ) ;
return CMD_RET_FAILURE ;
}
vsc9953_port_status_set ( parsed_cmd - > port , enabled ) ;
} else {
for ( i = 0 ; i < VSC9953_MAX_PORTS ; i + + )
vsc9953_port_status_set ( i , enabled ) ;
}
return CMD_RET_SUCCESS ;
}
static int vsc9953_port_config_key_func ( struct ethsw_command_def * parsed_cmd )
{
int i ;
if ( parsed_cmd - > port ! = ETHSW_CMD_PORT_ALL ) {
if ( ! VSC9953_PORT_CHECK ( parsed_cmd - > port ) ) {
printf ( " Invalid port number: %d \n " , parsed_cmd - > port ) ;
return CMD_RET_FAILURE ;
}
vsc9953_phy_autoneg ( parsed_cmd - > port ) ;
printf ( " %8s %8s %8s %8s %8s \n " ,
" Port " , " Status " , " Link " , " Speed " ,
" Duplex " ) ;
vsc9953_port_config_show ( parsed_cmd - > port ) ;
} else {
for ( i = 0 ; i < VSC9953_MAX_PORTS ; i + + )
vsc9953_phy_autoneg ( i ) ;
printf ( " %8s %8s %8s %8s %8s \n " ,
" Port " , " Status " , " Link " , " Speed " , " Duplex " ) ;
for ( i = 0 ; i < VSC9953_MAX_PORTS ; i + + )
vsc9953_port_config_show ( i ) ;
}
return CMD_RET_SUCCESS ;
}
static struct ethsw_command_func vsc9953_cmd_func = {
. ethsw_name = " L2 Switch VSC9953 " ,
. port_enable = & vsc9953_port_status_key_func ,
. port_disable = & vsc9953_port_status_key_func ,
. port_show = & vsc9953_port_config_key_func ,
} ;
# endif /* CONFIG_CMD_ETHSW */
/*****************************************************************************
At startup , the default configuration would be :
- HW learning enabled on all ports ; ( HW default )
@ -563,190 +723,11 @@ void vsc9953_init(bd_t *bis)
vsc9953_default_configuration ( ) ;
# ifdef CONFIG_CMD_ETHSW
if ( ethsw_define_functions ( & vsc9953_cmd_func ) < 0 )
debug ( " Unable to use \" ethsw \" commands \n " ) ;
# endif
printf ( " VSC9953 L2 switch initialized \n " ) ;
return ;
}
# ifdef CONFIG_VSC9953_CMD
/* Enable/disable status of a VSC9953 port */
static void vsc9953_port_status_set ( int port_no , u8 enabled )
{
struct vsc9953_qsys_reg * l2qsys_reg ;
/* Administrative down */
if ( ! vsc9953_l2sw . port [ port_no ] . enabled )
return ;
l2qsys_reg = ( struct vsc9953_qsys_reg * ) ( VSC9953_OFFSET +
VSC9953_QSYS_OFFSET ) ;
if ( enabled )
setbits_le32 ( & l2qsys_reg - > sys . switch_port_mode [ port_no ] ,
VSC9953_PORT_ENA ) ;
else
clrbits_le32 ( & l2qsys_reg - > sys . switch_port_mode [ port_no ] ,
VSC9953_PORT_ENA ) ;
}
/* Set all VSC9953 ports' status */
static void vsc9953_port_all_status_set ( u8 enabled )
{
int i ;
for ( i = 0 ; i < VSC9953_MAX_PORTS ; i + + )
vsc9953_port_status_set ( i , enabled ) ;
}
/* Start autonegotiation for a VSC9953 PHY */
static void vsc9953_phy_autoneg ( int port_no )
{
if ( ! vsc9953_l2sw . port [ port_no ] . phydev )
return ;
if ( vsc9953_l2sw . port [ port_no ] . phydev - > drv - > startup (
vsc9953_l2sw . port [ port_no ] . phydev ) )
printf ( " Failed to start PHY for port %d \n " , port_no ) ;
}
/* Start autonegotiation for all VSC9953 PHYs */
static void vsc9953_phy_all_autoneg ( void )
{
int i ;
for ( i = 0 ; i < VSC9953_MAX_PORTS ; i + + )
vsc9953_phy_autoneg ( i ) ;
}
/* Print a VSC9953 port's configuration */
static void vsc9953_port_config_show ( int port_no )
{
int speed ;
int duplex ;
int link ;
u8 enabled ;
u32 val ;
struct vsc9953_qsys_reg * l2qsys_reg ;
l2qsys_reg = ( struct vsc9953_qsys_reg * ) ( VSC9953_OFFSET +
VSC9953_QSYS_OFFSET ) ;
val = in_le32 ( & l2qsys_reg - > sys . switch_port_mode [ port_no ] ) ;
enabled = vsc9953_l2sw . port [ port_no ] . enabled & &
( val & VSC9953_PORT_ENA ) ;
/* internal ports (8 and 9) are fixed */
if ( VSC9953_INTERNAL_PORT_CHECK ( port_no ) ) {
link = 1 ;
speed = SPEED_2500 ;
duplex = DUPLEX_FULL ;
} else {
if ( vsc9953_l2sw . port [ port_no ] . phydev ) {
link = vsc9953_l2sw . port [ port_no ] . phydev - > link ;
speed = vsc9953_l2sw . port [ port_no ] . phydev - > speed ;
duplex = vsc9953_l2sw . port [ port_no ] . phydev - > duplex ;
} else {
link = - 1 ;
speed = - 1 ;
duplex = - 1 ;
}
}
printf ( " %8d " , port_no ) ;
printf ( " %8s " , enabled = = 1 ? " enabled " : " disabled " ) ;
printf ( " %8s " , link = = 1 ? " up " : " down " ) ;
switch ( speed ) {
case SPEED_10 :
printf ( " %8d " , 10 ) ;
break ;
case SPEED_100 :
printf ( " %8d " , 100 ) ;
break ;
case SPEED_1000 :
printf ( " %8d " , 1000 ) ;
break ;
case SPEED_2500 :
printf ( " %8d " , 2500 ) ;
break ;
case SPEED_10000 :
printf ( " %8d " , 10000 ) ;
break ;
default :
printf ( " %8s " , " - " ) ;
}
printf ( " %8s \n " , duplex = = DUPLEX_FULL ? " full " : " half " ) ;
}
/* Print VSC9953 ports' configuration */
static void vsc9953_port_all_config_show ( void )
{
int i ;
for ( i = 0 ; i < VSC9953_MAX_PORTS ; i + + )
vsc9953_port_config_show ( i ) ;
}
/* function to interpret commands starting with "ethsw " */
static int do_ethsw ( cmd_tbl_t * cmdtp , int flag , int argc , char * const argv [ ] )
{
u8 enable ;
u32 port ;
if ( argc < 4 )
return - 1 ;
if ( strcmp ( argv [ 1 ] , " port " ) )
return - 1 ;
if ( ! strcmp ( argv [ 3 ] , " show " ) ) {
if ( ! strcmp ( argv [ 2 ] , " all " ) ) {
vsc9953_phy_all_autoneg ( ) ;
printf ( " %8s %8s %8s %8s %8s \n " ,
" Port " , " Status " , " Link " , " Speed " ,
" Duplex " ) ;
vsc9953_port_all_config_show ( ) ;
return 0 ;
} else {
port = simple_strtoul ( argv [ 2 ] , NULL , 10 ) ;
if ( ! VSC9953_PORT_CHECK ( port ) )
return - 1 ;
vsc9953_phy_autoneg ( port ) ;
printf ( " %8s %8s %8s %8s %8s \n " ,
" Port " , " Status " , " Link " , " Speed " ,
" Duplex " ) ;
vsc9953_port_config_show ( port ) ;
return 0 ;
}
} else if ( ! strcmp ( argv [ 3 ] , " enable " ) ) {
enable = 1 ;
} else if ( ! strcmp ( argv [ 3 ] , " disable " ) ) {
enable = 0 ;
} else {
return - 1 ;
}
if ( ! strcmp ( argv [ 2 ] , " all " ) ) {
vsc9953_port_all_status_set ( enable ) ;
return 0 ;
} else {
port = simple_strtoul ( argv [ 2 ] , NULL , 10 ) ;
if ( ! VSC9953_PORT_CHECK ( port ) )
return - 1 ;
vsc9953_port_status_set ( port , enable ) ;
return 0 ;
}
return - 1 ;
}
U_BOOT_CMD ( ethsw , 5 , 0 , do_ethsw ,
" vsc9953 l2 switch commands " ,
" port <port_no> enable|disable \n "
" - enable/disable an l2 switch port \n "
" port_no=0..9; use \" all \" for all ports \n "
" ethsw port <port_no> show \n "
" - show an l2 switch port's configuration \n "
" port_no=0..9; use \" all \" for all ports \n "
) ;
# endif /* CONFIG_VSC9953_CMD */