2015-05-06 02:09:50 +03:00
/* net/dsa/mv88e6171.c - Marvell 88e6171 switch chip support
2014-09-13 01:58:44 +04:00
* Copyright ( c ) 2008 - 2009 Marvell Semiconductor
* Copyright ( c ) 2014 Claudio Leite < leitec @ staticky . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*/
# include <linux/delay.h>
# include <linux/jiffies.h>
# include <linux/list.h>
# include <linux/module.h>
# include <linux/netdevice.h>
# include <linux/phy.h>
# include <net/dsa.h>
# include "mv88e6xxx.h"
2014-09-15 21:00:27 +04:00
static char * mv88e6171_probe ( struct device * host_dev , int sw_addr )
2014-09-13 01:58:44 +04:00
{
2014-09-15 21:00:27 +04:00
struct mii_bus * bus = dsa_host_dev_to_mii_bus ( host_dev ) ;
2014-09-13 01:58:44 +04:00
int ret ;
2014-09-15 21:00:27 +04:00
if ( bus = = NULL )
return NULL ;
2015-04-02 05:06:39 +03:00
ret = __mv88e6xxx_reg_read ( bus , sw_addr , REG_PORT ( 0 ) , PORT_SWITCH_ID ) ;
2014-09-13 01:58:44 +04:00
if ( ret > = 0 ) {
2015-04-02 05:06:39 +03:00
if ( ( ret & 0xfff0 ) = = PORT_SWITCH_ID_6171 )
2014-09-13 01:58:44 +04:00
return " Marvell 88E6171 " ;
2015-05-06 02:09:51 +03:00
if ( ( ret & 0xfff0 ) = = PORT_SWITCH_ID_6175 )
return " Marvell 88E6175 " ;
if ( ( ret & 0xfff0 ) = = PORT_SWITCH_ID_6350 )
return " Marvell 88E6350 " ;
if ( ( ret & 0xfff0 ) = = PORT_SWITCH_ID_6351 )
return " Marvell 88E6351 " ;
2014-09-13 01:58:44 +04:00
}
return NULL ;
}
static int mv88e6171_setup_global ( struct dsa_switch * ds )
{
2015-05-06 02:09:49 +03:00
u32 upstream_port = dsa_upstream_port ( ds ) ;
2014-09-13 01:58:44 +04:00
int ret ;
2015-05-06 02:09:50 +03:00
u32 reg ;
2015-05-06 02:09:47 +03:00
ret = mv88e6xxx_setup_global ( ds ) ;
if ( ret )
return ret ;
2014-09-13 01:58:44 +04:00
2015-02-14 21:17:51 +03:00
/* Discard packets with excessive collisions, mask all
* interrupt sources , enable PPU .
2014-09-13 01:58:44 +04:00
*/
2015-05-06 02:09:49 +03:00
REG_WRITE ( REG_GLOBAL , GLOBAL_CONTROL ,
GLOBAL_CONTROL_PPU_ENABLE | GLOBAL_CONTROL_DISCARD_EXCESS ) ;
2014-09-13 01:58:44 +04:00
/* Configure the upstream port, and configure the upstream
* port as the port to which ingress and egress monitor frames
* are to be sent .
*/
2015-05-06 02:09:50 +03:00
reg = upstream_port < < GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
upstream_port < < GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
upstream_port < < GLOBAL_MONITOR_CONTROL_ARP_SHIFT |
upstream_port < < GLOBAL_MONITOR_CONTROL_MIRROR_SHIFT ;
REG_WRITE ( REG_GLOBAL , GLOBAL_MONITOR_CONTROL , reg ) ;
2014-09-13 01:58:44 +04:00
/* Disable remote management for now, and set the switch's
* DSA device number .
*/
2015-05-06 02:09:49 +03:00
REG_WRITE ( REG_GLOBAL , GLOBAL_CONTROL_2 , ds - > index & 0x1f ) ;
2014-09-13 01:58:44 +04:00
return 0 ;
}
static int mv88e6171_setup ( struct dsa_switch * ds )
{
2015-04-02 05:06:33 +03:00
struct mv88e6xxx_priv_state * ps = ds_to_priv ( ds ) ;
2014-09-13 01:58:44 +04:00
int ret ;
2015-03-27 04:36:28 +03:00
ret = mv88e6xxx_setup_common ( ds ) ;
if ( ret < 0 )
return ret ;
2014-09-13 01:58:44 +04:00
2015-04-02 05:06:33 +03:00
ps - > num_ports = 7 ;
2015-04-02 05:06:34 +03:00
ret = mv88e6xxx_switch_reset ( ds , true ) ;
2014-09-13 01:58:44 +04:00
if ( ret < 0 )
return ret ;
ret = mv88e6171_setup_global ( ds ) ;
if ( ret < 0 )
return ret ;
2015-05-06 02:09:48 +03:00
return mv88e6xxx_setup_ports ( ds ) ;
2014-09-13 01:58:44 +04:00
}
struct dsa_switch_driver mv88e6171_switch_driver = {
2014-10-25 01:44:05 +04:00
. tag_protocol = DSA_TAG_PROTO_EDSA ,
2014-09-13 01:58:44 +04:00
. priv_size = sizeof ( struct mv88e6xxx_priv_state ) ,
. probe = mv88e6171_probe ,
. setup = mv88e6171_setup ,
. set_addr = mv88e6xxx_set_addr_indirect ,
2015-04-02 05:06:36 +03:00
. phy_read = mv88e6xxx_phy_read_indirect ,
. phy_write = mv88e6xxx_phy_write_indirect ,
2014-09-13 01:58:44 +04:00
. poll_link = mv88e6xxx_poll_link ,
2015-04-02 05:06:38 +03:00
. get_strings = mv88e6xxx_get_strings ,
. get_ethtool_stats = mv88e6xxx_get_ethtool_stats ,
. get_sset_count = mv88e6xxx_get_sset_count ,
2014-11-16 00:24:52 +03:00
# ifdef CONFIG_NET_DSA_HWMON
. get_temp = mv88e6xxx_get_temp ,
# endif
2014-11-16 00:24:53 +03:00
. get_regs_len = mv88e6xxx_get_regs_len ,
. get_regs = mv88e6xxx_get_regs ,
2015-03-27 04:36:43 +03:00
. port_join_bridge = mv88e6xxx_join_bridge ,
. port_leave_bridge = mv88e6xxx_leave_bridge ,
. port_stp_update = mv88e6xxx_port_stp_update ,
. fdb_add = mv88e6xxx_port_fdb_add ,
. fdb_del = mv88e6xxx_port_fdb_del ,
. fdb_getnext = mv88e6xxx_port_fdb_getnext ,
2014-09-13 01:58:44 +04:00
} ;
MODULE_ALIAS ( " platform:mv88e6171 " ) ;
2015-05-06 02:09:51 +03:00
MODULE_ALIAS ( " platform:mv88e6175 " ) ;
MODULE_ALIAS ( " platform:mv88e6350 " ) ;
MODULE_ALIAS ( " platform:mv88e6351 " ) ;