@ -72,6 +72,7 @@ struct robo_switch {
char * device ; /* The device name string (ethX) */
u16 devid ; /* ROBO_DEVICE_ID_53xx */
bool is_5350 ;
u8 gmii ; /* gigabit mii */
struct ifreq ifr ;
struct net_device * dev ;
unsigned char port [ 6 ] ;
@ -147,7 +148,7 @@ static int robo_reg(__u8 page, __u8 reg, __u8 op)
printk ( KERN_ERR PFX " timeout in robo_reg on page %i and reg %i with op %i. \n " , page , reg , op ) ;
return 0 ;
return 1 ;
}
/*
@ -173,7 +174,7 @@ static __u32 robo_read32(__u8 page, __u8 reg)
{
robo_reg ( page , reg , REG_MII_ADDR_READ ) ;
return mdio_read ( ROBO_PHY_ADDR , REG_MII_DATA0 ) +
return mdio_read ( ROBO_PHY_ADDR , REG_MII_DATA0 ) |
( mdio_read ( ROBO_PHY_ADDR , REG_MII_DATA0 + 1 ) < < 16 ) ;
}
@ -188,21 +189,40 @@ static void robo_write16(__u8 page, __u8 reg, __u16 val16)
static void robo_write32 ( __u8 page , __u8 reg , __u32 val32 )
{
/* write data */
mdio_write ( ROBO_PHY_ADDR , REG_MII_DATA0 , val32 & 65535 ) ;
mdio_write ( ROBO_PHY_ADDR , REG_MII_DATA0 , val32 & 0xFFFF ) ;
mdio_write ( ROBO_PHY_ADDR , REG_MII_DATA0 + 1 , val32 > > 16 ) ;
robo_reg ( page , reg , REG_MII_ADDR_WRITE ) ;
}
/* checks that attached switch is 5325E/5350 */
static int robo_vlan5350 ( vo id)
/* checks that attached switch is 5325/5352/5354/5356/5357/53115 */
static int robo_vlan5350 ( __u32 phy id)
{
/* set vlan access id to 15 and read it back */
__u16 val16 = 15 ;
robo_write16 ( ROBO_VLAN_PAGE , ROBO_VLAN_TABLE_ACCESS_5350 , val16 ) ;
/* 5365 will refuse this as it does not have this reg */
return ( robo_read16 ( ROBO_VLAN_PAGE , ROBO_VLAN_TABLE_ACCESS_5350 ) = = val16 ) ;
if ( robo_read16 ( ROBO_VLAN_PAGE , ROBO_VLAN_TABLE_ACCESS_5350 ) ! = val16 )
return 0 ;
/* gigabit ? */
if ( mdio_read ( 0 , ROBO_MII_STAT ) & 0x0100 )
robo . gmii = ( ( mdio_read ( 0 , 0x0f ) & 0xf000 ) ! = 0 ) ;
/* 53115 ? */
if ( robo . gmii & & robo_read32 ( ROBO_STAT_PAGE , ROBO_LSA_IM_PORT ) ! = 0 ) {
robo_write16 ( ROBO_ARLIO_PAGE , ROBO_VTBL_INDX_5395 , val16 ) ;
robo_write16 ( ROBO_ARLIO_PAGE , ROBO_VTBL_ACCESS_5395 ,
( 1 < < 7 ) /* start */ | 1 /* read */ ) ;
if ( robo_read16 ( ROBO_ARLIO_PAGE , ROBO_VTBL_ACCESS_5395 ) = = 1 & &
robo_read16 ( ROBO_ARLIO_PAGE , ROBO_VTBL_INDX_5395 ) = = val16 )
return 4 ;
}
/* dirty trick for 5356/5357 */
if ( ( phyid & 0xfff0ffff ) = = 0x5da00362 | |
( phyid & 0xfff0ffff ) = = 0x5e000362 )
return 3 ;
/* 5325/5352/5354*/
return 1 ;
}
static int robo_switch_enable ( void )
@ -259,6 +279,7 @@ static int robo_probe(char *devname)
__u32 phyid ;
unsigned int i ;
int err = 1 ;
struct mii_ioctl_data * mii ;
printk ( KERN_INFO PFX " Probing device '%s' \n " , devname ) ;
strcpy ( robo . ifr . ifr_name , devname ) ;
@ -285,7 +306,7 @@ static int robo_probe(char *devname)
}
/* got phy address check for robo address */
struct mii_ioctl_data * mii = if_mii ( & robo . ifr ) ;
mii = if_mii ( & robo . ifr ) ;
if ( ( mii - > phy_id ! = ROBO_PHY_ADDR ) & &
( mii - > phy_id ! = ROBO_PHY_ADDR_BCM63XX ) & &
( mii - > phy_id ! = ROBO_PHY_ADDR_TG3 ) ) {
@ -310,7 +331,7 @@ static int robo_probe(char *devname)
}
if ( ! robo . devid )
robo . devid = ROBO_DEVICE_ID_5325 ; /* Fake it */
robo . is_5350 = robo_vlan5350 ( ) ;
robo . is_5350 = robo_vlan5350 ( phyid ) ;
robo_switch_reset ( ) ;
err = robo_switch_enable ( ) ;
@ -445,6 +466,80 @@ static int handle_enable_write(void *driver, char *buf, int nr)
return 0 ;
}
static int handle_port_enable_read ( void * driver , char * buf , int nr )
{
return sprintf ( buf , " %d \n " , ( ( robo_read16 ( ROBO_CTRL_PAGE , robo . port [ nr ] ) & 3 ) = = 3 ? 0 : 1 ) ) ;
}
static int handle_port_enable_write ( void * driver , char * buf , int nr )
{
u16 val16 ;
if ( buf [ 0 ] = = ' 0 ' )
val16 = 3 ; /* disabled */
else if ( buf [ 0 ] = = ' 1 ' )
val16 = 0 ; /* enabled */
else
return - EINVAL ;
robo_write16 ( ROBO_CTRL_PAGE , robo . port [ nr ] ,
( robo_read16 ( ROBO_CTRL_PAGE , robo . port [ nr ] ) & ~ 3 ) | val16 ) ;
return 0 ;
}
static int handle_port_media_read ( void * driver , char * buf , int nr )
{
u16 bmcr = mdio_read ( robo . port [ nr ] , MII_BMCR ) ;
int media , len ;
if ( bmcr & BMCR_ANENABLE )
media = SWITCH_MEDIA_AUTO ;
else {
if ( bmcr & BMCR_SPEED1000 )
media = SWITCH_MEDIA_1000 ;
else if ( bmcr & BMCR_SPEED100 )
media = SWITCH_MEDIA_100 ;
else
media = 0 ;
if ( bmcr & BMCR_FULLDPLX )
media | = SWITCH_MEDIA_FD ;
}
len = switch_print_media ( buf , media ) ;
return len + sprintf ( buf + len , " \n " ) ;
}
static int handle_port_media_write ( void * driver , char * buf , int nr )
{
int media = switch_parse_media ( buf ) ;
u16 bmcr , bmcr_mask ;
if ( media & SWITCH_MEDIA_AUTO )
bmcr = BMCR_ANENABLE | BMCR_ANRESTART ;
else {
if ( media & SWITCH_MEDIA_1000 ) {
if ( ! robo . gmii )
return - EINVAL ;
bmcr = BMCR_SPEED1000 ;
}
else if ( media & SWITCH_MEDIA_100 )
bmcr = BMCR_SPEED100 ;
else
bmcr = 0 ;
if ( media & SWITCH_MEDIA_FD )
bmcr | = BMCR_FULLDPLX ;
}
bmcr_mask = ~ ( BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_ANENABLE | BMCR_ANRESTART ) ;
mdio_write ( robo . port [ nr ] , MII_BMCR ,
( mdio_read ( robo . port [ nr ] , MII_BMCR ) & bmcr_mask ) | bmcr ) ;
return 0 ;
}
static int handle_enable_vlan_read ( void * driver , char * buf , int nr )
{
return sprintf ( buf , " %d \n " , ( ( ( robo_read16 ( ROBO_VLAN_PAGE , ROBO_VLAN_CTRL0 ) & ( 1 < < 7 ) ) = = ( 1 < < 7 ) ) ? 1 : 0 ) ) ;
@ -539,6 +634,17 @@ static int __init robo_init(void)
. write = handle_reset
} , { NULL , } ,
} ;
static const switch_config port [ ] = {
{
. name = " enable " ,
. read = handle_port_enable_read ,
. write = handle_port_enable_write
} , {
. name = " media " ,
. read = handle_port_media_read ,
. write = handle_port_media_write
} , { NULL , } ,
} ;
static const switch_config vlan [ ] = {
{
. name = " ports " ,
@ -554,7 +660,7 @@ static int __init robo_init(void)
. ports = 6 ,
. vlans = 16 ,
. driver_handlers = cfg ,
. port_handlers = NULL ,
. port_handlers = port ,
. vlan_handlers = vlan ,
} ;
if ( robo . devid ! = ROBO_DEVICE_ID_5325 ) {