2019-05-19 16:51:43 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2005-08-31 20:53:10 +04:00
/*
* ASIX AX8817X based USB 2.0 Ethernet Devices
2006-07-29 18:12:50 +04:00
* Copyright ( C ) 2003 - 2006 David Hollis < dhollis @ davehollis . com >
2005-08-31 20:53:10 +04:00
* Copyright ( C ) 2005 Phil Chang < pchang23 @ sbcglobal . net >
2006-07-29 18:12:50 +04:00
* Copyright ( C ) 2006 James Painter < jamie . painter @ iname . com >
2005-08-31 20:53:10 +04:00
* Copyright ( c ) 2002 - 2003 TiVo Inc .
*/
2012-07-13 09:26:30 +04:00
# include "asix.h"
2006-07-29 18:12:50 +04:00
# define PHY_MODE_MARVELL 0x0000
# define MII_MARVELL_LED_CTRL 0x0018
# define MII_MARVELL_STATUS 0x001b
# define MII_MARVELL_CTRL 0x0014
# define MARVELL_LED_MANUAL 0x0019
# define MARVELL_STATUS_HWCFG 0x0004
# define MARVELL_CTRL_TXDELAY 0x0002
# define MARVELL_CTRL_RXDELAY 0x0080
2005-08-31 20:53:10 +04:00
2011-11-15 11:12:39 +04:00
# define PHY_MODE_RTL8211CL 0x000C
2011-10-04 13:55:17 +04:00
2016-08-29 16:32:17 +03:00
# define AX88772A_PHY14H 0x14
# define AX88772A_PHY14H_DEFAULT 0x442C
# define AX88772A_PHY15H 0x15
# define AX88772A_PHY15H_DEFAULT 0x03C8
# define AX88772A_PHY16H 0x16
# define AX88772A_PHY16H_DEFAULT 0x4044
2005-08-31 20:53:10 +04:00
struct ax88172_int_data {
2007-12-22 20:42:36 +03:00
__le16 res1 ;
2005-08-31 20:53:10 +04:00
u8 link ;
2007-12-22 20:42:36 +03:00
__le16 res2 ;
2005-08-31 20:53:10 +04:00
u8 status ;
2007-12-22 20:42:36 +03:00
__le16 res3 ;
2010-06-02 22:10:09 +04:00
} __packed ;
2005-08-31 20:53:10 +04:00
2006-07-29 18:12:50 +04:00
static void asix_status ( struct usbnet * dev , struct urb * urb )
{
struct ax88172_int_data * event ;
int link ;
if ( urb - > actual_length < 8 )
return ;
event = urb - > transfer_buffer ;
link = event - > link & 0x01 ;
if ( netif_carrier_ok ( dev - > net ) ! = link ) {
2013-04-11 08:40:34 +04:00
usbnet_link_change ( dev , link , 1 ) ;
2010-02-17 13:30:23 +03:00
netdev_dbg ( dev - > net , " Link Status is: %d \n " , link ) ;
2006-07-29 18:12:50 +04:00
}
}
2012-11-22 01:35:17 +04:00
static void asix_set_netdev_dev_addr ( struct usbnet * dev , u8 * addr )
{
if ( is_valid_ether_addr ( addr ) ) {
memcpy ( dev - > net - > dev_addr , addr , ETH_ALEN ) ;
} else {
netdev_info ( dev - > net , " invalid hw address, using random \n " ) ;
eth_hw_addr_random ( dev - > net ) ;
}
}
2006-07-29 18:12:50 +04:00
/* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */
static u32 asix_get_phyid ( struct usbnet * dev )
2005-08-31 20:53:10 +04:00
{
2006-07-29 18:12:50 +04:00
int phy_reg ;
u32 phy_id ;
2011-11-15 11:12:40 +04:00
int i ;
2005-08-31 20:53:10 +04:00
2011-11-15 11:12:40 +04:00
/* Poll for the rare case the FW or phy isn't ready yet. */
for ( i = 0 ; i < 100 ; i + + ) {
phy_reg = asix_mdio_read ( dev - > net , dev - > mii . phy_id , MII_PHYSID1 ) ;
2016-08-29 16:32:16 +03:00
if ( phy_reg < 0 )
return 0 ;
2011-11-15 11:12:40 +04:00
if ( phy_reg ! = 0 & & phy_reg ! = 0xFFFF )
break ;
mdelay ( 1 ) ;
}
if ( phy_reg < = 0 | | phy_reg = = 0xFFFF )
2006-07-29 18:12:50 +04:00
return 0 ;
2005-08-31 20:53:10 +04:00
2006-07-29 18:12:50 +04:00
phy_id = ( phy_reg & 0xffff ) < < 16 ;
2005-08-31 20:53:10 +04:00
2006-07-29 18:12:50 +04:00
phy_reg = asix_mdio_read ( dev - > net , dev - > mii . phy_id , MII_PHYSID2 ) ;
if ( phy_reg < 0 )
return 0 ;
phy_id | = ( phy_reg & 0xffff ) ;
return phy_id ;
2005-08-31 20:53:10 +04:00
}
2006-07-29 18:12:50 +04:00
static u32 asix_get_link ( struct net_device * net )
{
struct usbnet * dev = netdev_priv ( net ) ;
return mii_link_ok ( & dev - > mii ) ;
}
static int asix_ioctl ( struct net_device * net , struct ifreq * rq , int cmd )
{
struct usbnet * dev = netdev_priv ( net ) ;
return generic_mii_ioctl ( & dev - > mii , if_mii ( rq ) , cmd , NULL ) ;
}
/* We need to override some ethtool_ops so we require our
own structure so we don ' t interfere with other usbnet
devices that may be connected at the same time . */
2009-09-02 12:03:33 +04:00
static const struct ethtool_ops ax88172_ethtool_ops = {
2006-07-29 18:12:50 +04:00
. get_drvinfo = asix_get_drvinfo ,
. get_link = asix_get_link ,
. get_msglevel = usbnet_get_msglevel ,
2005-08-31 20:53:10 +04:00
. set_msglevel = usbnet_set_msglevel ,
2006-03-29 05:15:42 +04:00
. get_wol = asix_get_wol ,
. set_wol = asix_set_wol ,
. get_eeprom_len = asix_get_eeprom_len ,
. get_eeprom = asix_get_eeprom ,
2012-07-19 04:23:07 +04:00
. set_eeprom = asix_set_eeprom ,
2006-10-09 02:08:01 +04:00
. nway_reset = usbnet_nway_reset ,
2021-04-06 02:13:41 +03:00
. get_link_ksettings = usbnet_get_link_ksettings_mii ,
. set_link_ksettings = usbnet_set_link_ksettings_mii ,
2005-08-31 20:53:10 +04:00
} ;
2006-07-29 18:12:50 +04:00
static void ax88172_set_multicast ( struct net_device * net )
2005-08-31 20:53:10 +04:00
{
struct usbnet * dev = netdev_priv ( net ) ;
2006-07-29 18:12:50 +04:00
struct asix_data * data = ( struct asix_data * ) & dev - > data ;
u8 rx_ctl = 0x8c ;
2005-08-31 20:53:10 +04:00
2006-07-29 18:12:50 +04:00
if ( net - > flags & IFF_PROMISC ) {
rx_ctl | = 0x01 ;
2009-12-03 10:58:21 +03:00
} else if ( net - > flags & IFF_ALLMULTI | |
2010-02-08 07:30:35 +03:00
netdev_mc_count ( net ) > AX_MAX_MCAST ) {
2006-07-29 18:12:50 +04:00
rx_ctl | = 0x02 ;
2010-02-08 07:30:35 +03:00
} else if ( netdev_mc_empty ( net ) ) {
2006-07-29 18:12:50 +04:00
/* just broadcast and directed */
} else {
/* We use the 20 byte dev->data
* for our 8 byte filter buffer
* to avoid allocating memory that
* is tricky to free later */
2010-04-02 01:22:57 +04:00
struct netdev_hw_addr * ha ;
2006-07-29 18:12:50 +04:00
u32 crc_bits ;
memset ( data - > multi_filter , 0 , AX_MCAST_FILTER_SIZE ) ;
/* Build the multicast hash filter. */
2010-04-02 01:22:57 +04:00
netdev_for_each_mc_addr ( ha , net ) {
crc_bits = ether_crc ( ETH_ALEN , ha - > addr ) > > 26 ;
2006-07-29 18:12:50 +04:00
data - > multi_filter [ crc_bits > > 3 ] | =
1 < < ( crc_bits & 7 ) ;
}
asix_write_cmd_async ( dev , AX_CMD_WRITE_MULTI_FILTER , 0 , 0 ,
AX_MCAST_FILTER_SIZE , data - > multi_filter ) ;
rx_ctl | = 0x10 ;
}
asix_write_cmd_async ( dev , AX_CMD_WRITE_RX_CTL , rx_ctl , 0 , 0 , NULL ) ;
}
static int ax88172_link_reset ( struct usbnet * dev )
{
u8 mode ;
2011-04-27 22:32:38 +04:00
struct ethtool_cmd ecmd = { . cmd = ETHTOOL_GSET } ;
2006-07-29 18:12:50 +04:00
mii_check_media ( & dev - > mii , 1 , 1 ) ;
mii_ethtool_gset ( & dev - > mii , & ecmd ) ;
mode = AX88172_MEDIUM_DEFAULT ;
if ( ecmd . duplex ! = DUPLEX_FULL )
mode | = ~ AX88172_MEDIUM_FD ;
2011-04-27 22:32:38 +04:00
netdev_dbg ( dev - > net , " ax88172_link_reset() speed: %u duplex: %d setting mode to 0x%04x \n " ,
ethtool_cmd_speed ( & ecmd ) , ecmd . duplex , mode ) ;
2006-07-29 18:12:50 +04:00
2016-08-29 16:32:15 +03:00
asix_write_medium_mode ( dev , mode , 0 ) ;
2006-07-29 18:12:50 +04:00
return 0 ;
2005-08-31 20:53:10 +04:00
}
2009-03-20 22:35:55 +03:00
static const struct net_device_ops ax88172_netdev_ops = {
. ndo_open = usbnet_open ,
. ndo_stop = usbnet_stop ,
. ndo_start_xmit = usbnet_start_xmit ,
. ndo_tx_timeout = usbnet_tx_timeout ,
. ndo_change_mtu = usbnet_change_mtu ,
2020-11-10 22:51:03 +03:00
. ndo_get_stats64 = dev_get_tstats64 ,
2009-03-20 22:35:55 +03:00
. ndo_set_mac_address = eth_mac_addr ,
. ndo_validate_addr = eth_validate_addr ,
. ndo_do_ioctl = asix_ioctl ,
2011-08-16 10:29:01 +04:00
. ndo_set_rx_mode = ax88172_set_multicast ,
2009-03-20 22:35:55 +03:00
} ;
2016-08-29 16:32:18 +03:00
static void asix_phy_reset ( struct usbnet * dev , unsigned int reset_bits )
{
unsigned int timeout = 5000 ;
asix_mdio_write ( dev - > net , dev - > mii . phy_id , MII_BMCR , reset_bits ) ;
/* give phy_id a chance to process reset */
udelay ( 500 ) ;
/* See IEEE 802.3 "22.2.4.1.1 Reset": 500ms max */
while ( timeout - - ) {
if ( asix_mdio_read ( dev - > net , dev - > mii . phy_id , MII_BMCR )
& BMCR_RESET )
udelay ( 100 ) ;
else
return ;
}
netdev_err ( dev - > net , " BMCR_RESET timeout on phy_id %d \n " ,
dev - > mii . phy_id ) ;
}
2006-03-29 05:15:42 +04:00
static int ax88172_bind ( struct usbnet * dev , struct usb_interface * intf )
2005-08-31 20:53:10 +04:00
{
int ret = 0 ;
2019-07-02 03:10:08 +03:00
u8 buf [ ETH_ALEN ] = { 0 } ;
2005-08-31 20:53:10 +04:00
int i ;
unsigned long gpio_bits = dev - > driver_info - > data ;
usbnet_get_endpoints ( dev , intf ) ;
/* Toggle the GPIOs in a manufacturer/model specific way */
for ( i = 2 ; i > = 0 ; i - - ) {
2011-10-04 13:55:18 +04:00
ret = asix_write_cmd ( dev , AX_CMD_WRITE_GPIOS ,
2016-08-29 16:32:15 +03:00
( gpio_bits > > ( i * 8 ) ) & 0xff , 0 , 0 , NULL , 0 ) ;
2011-10-04 13:55:18 +04:00
if ( ret < 0 )
2007-12-22 20:42:36 +03:00
goto out ;
2005-08-31 20:53:10 +04:00
msleep ( 5 ) ;
}
2016-08-29 16:32:15 +03:00
ret = asix_write_rx_ctl ( dev , 0x80 , 0 ) ;
2011-10-04 13:55:18 +04:00
if ( ret < 0 )
2007-12-22 20:42:36 +03:00
goto out ;
2005-08-31 20:53:10 +04:00
/* Get the MAC address */
2016-08-29 16:32:15 +03:00
ret = asix_read_cmd ( dev , AX88172_CMD_READ_NODE_ID ,
0 , 0 , ETH_ALEN , buf , 0 ) ;
2011-10-04 13:55:18 +04:00
if ( ret < 0 ) {
2012-09-19 13:46:14 +04:00
netdev_dbg ( dev - > net , " read AX_CMD_READ_NODE_ID failed: %d \n " ,
ret ) ;
2007-12-22 20:42:36 +03:00
goto out ;
2005-08-31 20:53:10 +04:00
}
2012-11-22 01:35:17 +04:00
asix_set_netdev_dev_addr ( dev , buf ) ;
2005-08-31 20:53:10 +04:00
/* Initialize MII structure */
dev - > mii . dev = dev - > net ;
2006-03-29 05:15:42 +04:00
dev - > mii . mdio_read = asix_mdio_read ;
dev - > mii . mdio_write = asix_mdio_write ;
2005-08-31 20:53:10 +04:00
dev - > mii . phy_id_mask = 0x3f ;
dev - > mii . reg_num_mask = 0x1f ;
2021-06-07 11:27:21 +03:00
dev - > mii . phy_id = asix_read_phy_addr ( dev , true ) ;
if ( dev - > mii . phy_id < 0 )
return dev - > mii . phy_id ;
2005-08-31 20:53:10 +04:00
2009-03-20 22:35:55 +03:00
dev - > net - > netdev_ops = & ax88172_netdev_ops ;
2006-03-29 05:15:42 +04:00
dev - > net - > ethtool_ops = & ax88172_ethtool_ops ;
2012-07-05 08:31:01 +04:00
dev - > net - > needed_headroom = 4 ; /* cf asix_tx_fixup() */
dev - > net - > needed_tailroom = 4 ; /* cf asix_tx_fixup() */
2005-08-31 20:53:10 +04:00
2016-08-29 16:32:18 +03:00
asix_phy_reset ( dev , BMCR_RESET ) ;
2006-07-29 18:12:50 +04:00
asix_mdio_write ( dev - > net , dev - > mii . phy_id , MII_ADVERTISE ,
2005-08-31 20:53:10 +04:00
ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP ) ;
mii_nway_restart ( & dev - > mii ) ;
return 0 ;
2007-12-22 20:42:36 +03:00
out :
2005-08-31 20:53:10 +04:00
return ret ;
}
2009-09-02 12:03:33 +04:00
static const struct ethtool_ops ax88772_ethtool_ops = {
2006-03-29 05:15:42 +04:00
. get_drvinfo = asix_get_drvinfo ,
2021-06-07 11:27:23 +03:00
. get_link = usbnet_get_link ,
2005-08-31 20:53:10 +04:00
. get_msglevel = usbnet_get_msglevel ,
. set_msglevel = usbnet_set_msglevel ,
2006-03-29 05:15:42 +04:00
. get_wol = asix_get_wol ,
. set_wol = asix_set_wol ,
. get_eeprom_len = asix_get_eeprom_len ,
. get_eeprom = asix_get_eeprom ,
2012-07-19 04:23:07 +04:00
. set_eeprom = asix_set_eeprom ,
2021-06-07 11:27:23 +03:00
. nway_reset = phy_ethtool_nway_reset ,
. get_link_ksettings = phy_ethtool_get_link_ksettings ,
. set_link_ksettings = phy_ethtool_set_link_ksettings ,
2005-08-31 20:53:10 +04:00
} ;
2011-10-04 13:55:16 +04:00
static int ax88772_reset ( struct usbnet * dev )
2016-08-29 16:32:15 +03:00
{
struct asix_data * data = ( struct asix_data * ) & dev - > data ;
2021-06-07 11:27:23 +03:00
struct asix_common_private * priv = dev - > driver_priv ;
2016-08-29 16:32:15 +03:00
int ret ;
/* Rewrite MAC address */
ether_addr_copy ( data - > mac_addr , dev - > net - > dev_addr ) ;
ret = asix_write_cmd ( dev , AX_CMD_WRITE_NODE_ID , 0 , 0 ,
ETH_ALEN , data - > mac_addr , 0 ) ;
if ( ret < 0 )
goto out ;
/* Set RX_CTL to default values with 2k buffer, and enable cactus */
ret = asix_write_rx_ctl ( dev , AX_DEFAULT_RX_CTL , 0 ) ;
if ( ret < 0 )
goto out ;
2017-02-28 14:58:22 +03:00
ret = asix_write_medium_mode ( dev , AX88772_MEDIUM_DEFAULT , 0 ) ;
2016-08-29 16:32:15 +03:00
if ( ret < 0 )
goto out ;
2021-06-07 11:27:23 +03:00
phy_start ( priv - > phydev ) ;
2016-08-29 16:32:15 +03:00
return 0 ;
out :
return ret ;
}
static int ax88772_hw_reset ( struct usbnet * dev , int in_pm )
2005-08-31 20:53:10 +04:00
{
2012-01-10 10:40:17 +04:00
struct asix_data * data = ( struct asix_data * ) & dev - > data ;
2007-01-12 02:39:16 +03:00
int ret , embd_phy ;
2006-07-29 18:12:50 +04:00
u16 rx_ctl ;
2005-08-31 20:53:10 +04:00
2016-08-29 16:32:15 +03:00
ret = asix_write_gpio ( dev , AX_GPIO_RSE | AX_GPIO_GPO_2 |
AX_GPIO_GPO2EN , 5 , in_pm ) ;
2011-10-04 13:55:18 +04:00
if ( ret < 0 )
2007-12-22 20:42:36 +03:00
goto out ;
2005-08-31 20:53:10 +04:00
2016-08-29 16:32:15 +03:00
embd_phy = ( ( dev - > mii . phy_id & 0x1f ) = = 0x10 ? 1 : 0 ) ;
2011-10-04 13:55:16 +04:00
2016-08-29 16:32:15 +03:00
ret = asix_write_cmd ( dev , AX_CMD_SW_PHY_SELECT , embd_phy ,
0 , 0 , NULL , in_pm ) ;
2011-10-04 13:55:18 +04:00
if ( ret < 0 ) {
2012-09-19 13:46:14 +04:00
netdev_dbg ( dev - > net , " Select PHY #1 failed: %d \n " , ret ) ;
2007-12-22 20:42:36 +03:00
goto out ;
2005-08-31 20:53:10 +04:00
}
2016-08-29 16:32:15 +03:00
if ( embd_phy ) {
ret = asix_sw_reset ( dev , AX_SWRESET_IPPD , in_pm ) ;
if ( ret < 0 )
goto out ;
2005-08-31 20:53:10 +04:00
2016-08-29 16:32:15 +03:00
usleep_range ( 10000 , 11000 ) ;
2011-10-04 13:55:18 +04:00
2016-08-29 16:32:15 +03:00
ret = asix_sw_reset ( dev , AX_SWRESET_CLEAR , in_pm ) ;
if ( ret < 0 )
goto out ;
2005-08-31 20:53:10 +04:00
2016-08-29 16:32:15 +03:00
msleep ( 60 ) ;
2011-10-04 13:55:16 +04:00
2016-08-29 16:32:15 +03:00
ret = asix_sw_reset ( dev , AX_SWRESET_IPRL | AX_SWRESET_PRL ,
in_pm ) ;
2011-10-04 13:55:18 +04:00
if ( ret < 0 )
2007-12-22 20:42:36 +03:00
goto out ;
2011-10-04 13:55:18 +04:00
} else {
2016-08-29 16:32:15 +03:00
ret = asix_sw_reset ( dev , AX_SWRESET_IPPD | AX_SWRESET_PRL ,
in_pm ) ;
2011-10-04 13:55:18 +04:00
if ( ret < 0 )
2007-12-22 20:42:36 +03:00
goto out ;
2007-01-12 02:39:16 +03:00
}
2005-08-31 20:53:10 +04:00
msleep ( 150 ) ;
2016-08-29 16:32:15 +03:00
if ( in_pm & & ( ! asix_mdio_read_nopm ( dev - > net , dev - > mii . phy_id ,
MII_PHYSID1 ) ) ) {
ret = - EIO ;
goto out ;
}
ret = asix_write_rx_ctl ( dev , AX_DEFAULT_RX_CTL , in_pm ) ;
if ( ret < 0 )
goto out ;
ret = asix_write_medium_mode ( dev , AX88772_MEDIUM_DEFAULT , in_pm ) ;
2011-10-04 13:55:18 +04:00
if ( ret < 0 )
2007-12-22 20:42:36 +03:00
goto out ;
2005-08-31 20:53:10 +04:00
2016-08-29 16:32:15 +03:00
ret = asix_write_cmd ( dev , AX_CMD_WRITE_IPG0 ,
AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT ,
AX88772_IPG2_DEFAULT , 0 , NULL , in_pm ) ;
if ( ret < 0 ) {
netdev_dbg ( dev - > net , " Write IPG,IPG1,IPG2 failed: %d \n " , ret ) ;
goto out ;
}
2006-07-29 18:12:50 +04:00
2016-08-29 16:32:15 +03:00
/* Rewrite MAC address */
ether_addr_copy ( data - > mac_addr , dev - > net - > dev_addr ) ;
ret = asix_write_cmd ( dev , AX_CMD_WRITE_NODE_ID , 0 , 0 ,
ETH_ALEN , data - > mac_addr , in_pm ) ;
2011-10-04 13:55:18 +04:00
if ( ret < 0 )
2007-12-22 20:42:36 +03:00
goto out ;
2005-08-31 20:53:10 +04:00
2016-08-29 16:32:15 +03:00
/* Set RX_CTL to default values with 2k buffer, and enable cactus */
ret = asix_write_rx_ctl ( dev , AX_DEFAULT_RX_CTL , in_pm ) ;
if ( ret < 0 )
goto out ;
rx_ctl = asix_read_rx_ctl ( dev , in_pm ) ;
netdev_dbg ( dev - > net , " RX_CTL is 0x%04x after all initializations \n " ,
rx_ctl ) ;
rx_ctl = asix_read_medium_status ( dev , in_pm ) ;
netdev_dbg ( dev - > net ,
" Medium Status is 0x%04x after all initializations \n " ,
rx_ctl ) ;
return 0 ;
out :
return ret ;
}
static int ax88772a_hw_reset ( struct usbnet * dev , int in_pm )
{
struct asix_data * data = ( struct asix_data * ) & dev - > data ;
int ret , embd_phy ;
2016-08-29 16:32:17 +03:00
u16 rx_ctl , phy14h , phy15h , phy16h ;
2016-08-29 16:32:15 +03:00
u8 chipcode = 0 ;
2006-03-29 05:15:42 +04:00
2016-08-29 16:32:15 +03:00
ret = asix_write_gpio ( dev , AX_GPIO_RSE , 5 , in_pm ) ;
2011-10-04 13:55:18 +04:00
if ( ret < 0 )
2007-12-22 20:42:36 +03:00
goto out ;
2005-08-31 20:53:10 +04:00
2016-08-29 16:32:15 +03:00
embd_phy = ( ( dev - > mii . phy_id & 0x1f ) = = 0x10 ? 1 : 0 ) ;
2005-08-31 20:53:10 +04:00
2016-08-29 16:32:15 +03:00
ret = asix_write_cmd ( dev , AX_CMD_SW_PHY_SELECT , embd_phy |
AX_PHYSEL_SSEN , 0 , 0 , NULL , in_pm ) ;
if ( ret < 0 ) {
netdev_dbg ( dev - > net , " Select PHY #1 failed: %d \n " , ret ) ;
goto out ;
}
usleep_range ( 10000 , 11000 ) ;
2005-08-31 20:53:10 +04:00
2016-08-29 16:32:15 +03:00
ret = asix_sw_reset ( dev , AX_SWRESET_IPPD | AX_SWRESET_IPRL , in_pm ) ;
2011-10-04 13:55:18 +04:00
if ( ret < 0 )
2007-12-22 20:42:36 +03:00
goto out ;
2005-08-31 20:53:10 +04:00
2016-08-29 16:32:15 +03:00
usleep_range ( 10000 , 11000 ) ;
ret = asix_sw_reset ( dev , AX_SWRESET_IPRL , in_pm ) ;
if ( ret < 0 )
goto out ;
msleep ( 160 ) ;
ret = asix_sw_reset ( dev , AX_SWRESET_CLEAR , in_pm ) ;
if ( ret < 0 )
goto out ;
ret = asix_sw_reset ( dev , AX_SWRESET_IPRL , in_pm ) ;
if ( ret < 0 )
goto out ;
msleep ( 200 ) ;
if ( in_pm & & ( ! asix_mdio_read_nopm ( dev - > net , dev - > mii . phy_id ,
MII_PHYSID1 ) ) ) {
ret = - 1 ;
goto out ;
}
ret = asix_read_cmd ( dev , AX_CMD_STATMNGSTS_REG , 0 ,
0 , 1 , & chipcode , in_pm ) ;
if ( ret < 0 )
goto out ;
if ( ( chipcode & AX_CHIPCODE_MASK ) = = AX_AX88772B_CHIPCODE ) {
ret = asix_write_cmd ( dev , AX_QCTCTRL , 0x8000 , 0x8001 ,
0 , NULL , in_pm ) ;
if ( ret < 0 ) {
netdev_dbg ( dev - > net , " Write BQ setting failed: %d \n " ,
ret ) ;
goto out ;
}
2016-08-29 16:32:17 +03:00
} else if ( ( chipcode & AX_CHIPCODE_MASK ) = = AX_AX88772A_CHIPCODE ) {
/* Check if the PHY registers have default settings */
phy14h = asix_mdio_read_nopm ( dev - > net , dev - > mii . phy_id ,
AX88772A_PHY14H ) ;
phy15h = asix_mdio_read_nopm ( dev - > net , dev - > mii . phy_id ,
AX88772A_PHY15H ) ;
phy16h = asix_mdio_read_nopm ( dev - > net , dev - > mii . phy_id ,
AX88772A_PHY16H ) ;
netdev_dbg ( dev - > net ,
" 772a_hw_reset: MR20=0x%x MR21=0x%x MR22=0x%x \n " ,
phy14h , phy15h , phy16h ) ;
/* Restore PHY registers default setting if not */
if ( phy14h ! = AX88772A_PHY14H_DEFAULT )
asix_mdio_write_nopm ( dev - > net , dev - > mii . phy_id ,
AX88772A_PHY14H ,
AX88772A_PHY14H_DEFAULT ) ;
if ( phy15h ! = AX88772A_PHY15H_DEFAULT )
asix_mdio_write_nopm ( dev - > net , dev - > mii . phy_id ,
AX88772A_PHY15H ,
AX88772A_PHY15H_DEFAULT ) ;
if ( phy16h ! = AX88772A_PHY16H_DEFAULT )
asix_mdio_write_nopm ( dev - > net , dev - > mii . phy_id ,
AX88772A_PHY16H ,
AX88772A_PHY16H_DEFAULT ) ;
2016-08-29 16:32:15 +03:00
}
2011-10-04 13:55:18 +04:00
ret = asix_write_cmd ( dev , AX_CMD_WRITE_IPG0 ,
2005-08-31 20:53:10 +04:00
AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT ,
2016-08-29 16:32:15 +03:00
AX88772_IPG2_DEFAULT , 0 , NULL , in_pm ) ;
2011-10-04 13:55:18 +04:00
if ( ret < 0 ) {
2012-09-19 13:46:14 +04:00
netdev_dbg ( dev - > net , " Write IPG,IPG1,IPG2 failed: %d \n " , ret ) ;
2007-12-22 20:42:36 +03:00
goto out ;
2005-08-31 20:53:10 +04:00
}
2012-01-10 10:40:17 +04:00
/* Rewrite MAC address */
memcpy ( data - > mac_addr , dev - > net - > dev_addr , ETH_ALEN ) ;
ret = asix_write_cmd ( dev , AX_CMD_WRITE_NODE_ID , 0 , 0 , ETH_ALEN ,
2016-08-29 16:32:15 +03:00
data - > mac_addr , in_pm ) ;
if ( ret < 0 )
goto out ;
/* Set RX_CTL to default values with 2k buffer, and enable cactus */
ret = asix_write_rx_ctl ( dev , AX_DEFAULT_RX_CTL , in_pm ) ;
2012-01-10 10:40:17 +04:00
if ( ret < 0 )
goto out ;
2016-08-29 16:32:15 +03:00
ret = asix_write_medium_mode ( dev , AX88772_MEDIUM_DEFAULT , in_pm ) ;
if ( ret < 0 )
return ret ;
2005-08-31 20:53:10 +04:00
/* Set RX_CTL to default values with 2k buffer, and enable cactus */
2016-08-29 16:32:15 +03:00
ret = asix_write_rx_ctl ( dev , AX_DEFAULT_RX_CTL , in_pm ) ;
2011-10-04 13:55:18 +04:00
if ( ret < 0 )
2007-12-22 20:42:36 +03:00
goto out ;
2005-08-31 20:53:10 +04:00
2016-08-29 16:32:15 +03:00
rx_ctl = asix_read_rx_ctl ( dev , in_pm ) ;
2012-09-19 13:46:14 +04:00
netdev_dbg ( dev - > net , " RX_CTL is 0x%04x after all initializations \n " ,
rx_ctl ) ;
2006-07-29 18:12:50 +04:00
2016-08-29 16:32:15 +03:00
rx_ctl = asix_read_medium_status ( dev , in_pm ) ;
2012-09-19 13:46:14 +04:00
netdev_dbg ( dev - > net ,
" Medium Status is 0x%04x after all initializations \n " ,
rx_ctl ) ;
2006-07-29 18:12:50 +04:00
2011-10-04 13:55:16 +04:00
return 0 ;
out :
return ret ;
}
static const struct net_device_ops ax88772_netdev_ops = {
. ndo_open = usbnet_open ,
. ndo_stop = usbnet_stop ,
. ndo_start_xmit = usbnet_start_xmit ,
. ndo_tx_timeout = usbnet_tx_timeout ,
. ndo_change_mtu = usbnet_change_mtu ,
2020-11-10 22:51:03 +03:00
. ndo_get_stats64 = dev_get_tstats64 ,
2011-10-04 13:55:16 +04:00
. ndo_set_mac_address = asix_set_mac_address ,
. ndo_validate_addr = eth_validate_addr ,
2021-06-07 11:27:23 +03:00
. ndo_do_ioctl = phy_do_ioctl_running ,
2011-10-04 13:55:16 +04:00
. ndo_set_rx_mode = asix_set_multicast ,
} ;
2016-08-29 16:32:15 +03:00
static void ax88772_suspend ( struct usbnet * dev )
{
struct asix_common_private * priv = dev - > driver_priv ;
2016-08-29 16:32:17 +03:00
u16 medium ;
/* Stop MAC operation */
2016-11-30 11:29:08 +03:00
medium = asix_read_medium_status ( dev , 1 ) ;
2016-08-29 16:32:17 +03:00
medium & = ~ AX_MEDIUM_RE ;
2016-11-30 11:29:08 +03:00
asix_write_medium_mode ( dev , medium , 1 ) ;
2016-08-29 16:32:17 +03:00
netdev_dbg ( dev - > net , " ax88772_suspend: medium=0x%04x \n " ,
2016-11-30 11:29:08 +03:00
asix_read_medium_status ( dev , 1 ) ) ;
2016-08-29 16:32:15 +03:00
/* Preserve BMCR for restoring */
priv - > presvd_phy_bmcr =
asix_mdio_read_nopm ( dev - > net , dev - > mii . phy_id , MII_BMCR ) ;
/* Preserve ANAR for restoring */
priv - > presvd_phy_advertise =
asix_mdio_read_nopm ( dev - > net , dev - > mii . phy_id , MII_ADVERTISE ) ;
}
static int asix_suspend ( struct usb_interface * intf , pm_message_t message )
{
struct usbnet * dev = usb_get_intfdata ( intf ) ;
struct asix_common_private * priv = dev - > driver_priv ;
2017-11-06 15:26:46 +03:00
if ( priv & & priv - > suspend )
2016-08-29 16:32:15 +03:00
priv - > suspend ( dev ) ;
return usbnet_suspend ( intf , message ) ;
}
static void ax88772_restore_phy ( struct usbnet * dev )
{
struct asix_common_private * priv = dev - > driver_priv ;
if ( priv - > presvd_phy_advertise ) {
/* Restore Advertisement control reg */
asix_mdio_write_nopm ( dev - > net , dev - > mii . phy_id , MII_ADVERTISE ,
priv - > presvd_phy_advertise ) ;
/* Restore BMCR */
2018-07-17 14:17:09 +03:00
if ( priv - > presvd_phy_bmcr & BMCR_ANENABLE )
priv - > presvd_phy_bmcr | = BMCR_ANRESTART ;
2016-08-29 16:32:15 +03:00
asix_mdio_write_nopm ( dev - > net , dev - > mii . phy_id , MII_BMCR ,
priv - > presvd_phy_bmcr ) ;
priv - > presvd_phy_advertise = 0 ;
priv - > presvd_phy_bmcr = 0 ;
}
}
static void ax88772_resume ( struct usbnet * dev )
{
int i ;
for ( i = 0 ; i < 3 ; i + + )
if ( ! ax88772_hw_reset ( dev , 1 ) )
break ;
ax88772_restore_phy ( dev ) ;
}
static void ax88772a_resume ( struct usbnet * dev )
{
int i ;
for ( i = 0 ; i < 3 ; i + + ) {
if ( ! ax88772a_hw_reset ( dev , 1 ) )
break ;
}
ax88772_restore_phy ( dev ) ;
}
static int asix_resume ( struct usb_interface * intf )
{
struct usbnet * dev = usb_get_intfdata ( intf ) ;
struct asix_common_private * priv = dev - > driver_priv ;
2017-11-06 15:26:46 +03:00
if ( priv & & priv - > resume )
2016-08-29 16:32:15 +03:00
priv - > resume ( dev ) ;
return usbnet_resume ( intf ) ;
}
2021-06-07 11:27:23 +03:00
static int ax88772_init_mdio ( struct usbnet * dev )
{
struct asix_common_private * priv = dev - > driver_priv ;
priv - > mdio = devm_mdiobus_alloc ( & dev - > udev - > dev ) ;
if ( ! priv - > mdio )
return - ENOMEM ;
priv - > mdio - > priv = dev ;
priv - > mdio - > read = & asix_mdio_bus_read ;
priv - > mdio - > write = & asix_mdio_bus_write ;
priv - > mdio - > name = " Asix MDIO Bus " ;
/* mii bus name is usb-<usb bus number>-<usb device number> */
snprintf ( priv - > mdio - > id , MII_BUS_ID_SIZE , " usb-%03d:%03d " ,
dev - > udev - > bus - > busnum , dev - > udev - > devnum ) ;
return devm_mdiobus_register ( & dev - > udev - > dev , priv - > mdio ) ;
}
static int ax88772_init_phy ( struct usbnet * dev )
{
struct asix_common_private * priv = dev - > driver_priv ;
int ret ;
priv - > phy_addr = asix_read_phy_addr ( dev , true ) ;
if ( priv - > phy_addr < 0 )
return priv - > phy_addr ;
snprintf ( priv - > phy_name , sizeof ( priv - > phy_name ) , PHY_ID_FMT ,
priv - > mdio - > id , priv - > phy_addr ) ;
priv - > phydev = phy_connect ( dev - > net , priv - > phy_name , & asix_adjust_link ,
PHY_INTERFACE_MODE_INTERNAL ) ;
if ( IS_ERR ( priv - > phydev ) ) {
netdev_err ( dev - > net , " Could not connect to PHY device %s \n " ,
priv - > phy_name ) ;
ret = PTR_ERR ( priv - > phydev ) ;
return ret ;
}
phy_attached_info ( priv - > phydev ) ;
return 0 ;
}
2011-10-04 13:55:16 +04:00
static int ax88772_bind ( struct usbnet * dev , struct usb_interface * intf )
{
2019-07-02 03:10:08 +03:00
u8 buf [ ETH_ALEN ] = { 0 } , chipcode = 0 ;
2016-08-29 16:32:15 +03:00
struct asix_common_private * priv ;
2021-06-07 11:27:23 +03:00
int ret , i ;
u32 phyid ;
2011-10-04 13:55:16 +04:00
2018-07-03 18:06:49 +03:00
usbnet_get_endpoints ( dev , intf ) ;
2011-10-04 13:55:16 +04:00
2018-07-03 18:06:49 +03:00
/* Maybe the boot loader passed the MAC address via device tree */
if ( ! eth_platform_get_mac_address ( & dev - > udev - > dev , buf ) ) {
netif_dbg ( dev , ifup , dev - > net ,
" MAC address read from device tree " ) ;
2013-01-16 08:24:06 +04:00
} else {
2018-07-03 18:06:49 +03:00
/* Try getting the MAC address from EEPROM */
if ( dev - > driver_info - > data & FLAG_EEPROM_MAC ) {
for ( i = 0 ; i < ( ETH_ALEN > > 1 ) ; i + + ) {
ret = asix_read_cmd ( dev , AX_CMD_READ_EEPROM ,
0x04 + i , 0 , 2 , buf + i * 2 ,
0 ) ;
if ( ret < 0 )
break ;
}
} else {
ret = asix_read_cmd ( dev , AX_CMD_READ_NODE_ID ,
0 , 0 , ETH_ALEN , buf , 0 ) ;
}
2013-01-16 08:24:06 +04:00
2018-07-03 18:06:49 +03:00
if ( ret < 0 ) {
netdev_dbg ( dev - > net , " Failed to read MAC address: %d \n " ,
ret ) ;
return ret ;
}
2011-10-04 13:55:16 +04:00
}
2012-11-22 01:35:17 +04:00
asix_set_netdev_dev_addr ( dev , buf ) ;
2011-10-04 13:55:16 +04:00
dev - > net - > netdev_ops = & ax88772_netdev_ops ;
dev - > net - > ethtool_ops = & ax88772_ethtool_ops ;
2012-07-05 08:31:01 +04:00
dev - > net - > needed_headroom = 4 ; /* cf asix_tx_fixup() */
dev - > net - > needed_tailroom = 4 ; /* cf asix_tx_fixup() */
2011-10-04 13:55:16 +04:00
2016-08-29 16:32:15 +03:00
asix_read_cmd ( dev , AX_CMD_STATMNGSTS_REG , 0 , 0 , 1 , & chipcode , 0 ) ;
chipcode & = AX_CHIPCODE_MASK ;
2011-11-15 11:12:41 +04:00
2019-01-24 08:48:49 +03:00
ret = ( chipcode = = AX_AX88772_CHIPCODE ) ? ax88772_hw_reset ( dev , 0 ) :
ax88772a_hw_reset ( dev , 0 ) ;
if ( ret < 0 ) {
netdev_dbg ( dev - > net , " Failed to reset AX88772: %d \n " , ret ) ;
return ret ;
}
2011-11-15 11:12:41 +04:00
/* Read PHYID register *AFTER* the PHY was reset properly */
phyid = asix_get_phyid ( dev ) ;
2012-09-19 13:46:14 +04:00
netdev_dbg ( dev - > net , " PHYID=0x%08x \n " , phyid ) ;
2011-11-15 11:12:41 +04:00
2005-08-31 20:53:10 +04:00
/* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
if ( dev - > driver_info - > flags & FLAG_FRAMING_AX ) {
/* hard_mtu is still the default - the device does not support
jumbo eth frames */
dev - > rx_urb_size = 2048 ;
}
2011-10-04 13:55:18 +04:00
2021-06-07 11:27:20 +03:00
priv = devm_kzalloc ( & dev - > udev - > dev , sizeof ( * priv ) , GFP_KERNEL ) ;
if ( ! priv )
2013-01-16 08:24:07 +04:00
return - ENOMEM ;
2021-06-07 11:27:20 +03:00
dev - > driver_priv = priv ;
2016-08-29 16:32:15 +03:00
priv - > presvd_phy_bmcr = 0 ;
priv - > presvd_phy_advertise = 0 ;
if ( chipcode = = AX_AX88772_CHIPCODE ) {
priv - > resume = ax88772_resume ;
priv - > suspend = ax88772_suspend ;
} else {
priv - > resume = ax88772a_resume ;
priv - > suspend = ax88772_suspend ;
}
2021-06-07 11:27:23 +03:00
ret = ax88772_init_mdio ( dev ) ;
if ( ret )
return ret ;
return ax88772_init_phy ( dev ) ;
}
static int ax88772_stop ( struct usbnet * dev )
{
struct asix_common_private * priv = dev - > driver_priv ;
/* On unplugged USB, we will get MDIO communication errors and the
* PHY will be set in to PHY_HALTED state .
*/
if ( priv - > phydev - > state ! = PHY_HALTED )
phy_stop ( priv - > phydev ) ;
2005-08-31 20:53:10 +04:00
return 0 ;
}
2013-01-18 19:36:56 +04:00
static void ax88772_unbind ( struct usbnet * dev , struct usb_interface * intf )
2013-01-16 08:24:07 +04:00
{
2021-06-07 11:27:23 +03:00
struct asix_common_private * priv = dev - > driver_priv ;
phy_disconnect ( priv - > phydev ) ;
2017-08-07 11:50:16 +03:00
asix_rx_fixup_common_free ( dev - > driver_priv ) ;
2013-01-16 08:24:07 +04:00
}
2012-01-05 23:10:23 +04:00
static const struct ethtool_ops ax88178_ethtool_ops = {
2006-07-29 18:12:50 +04:00
. get_drvinfo = asix_get_drvinfo ,
. get_link = asix_get_link ,
. get_msglevel = usbnet_get_msglevel ,
. set_msglevel = usbnet_set_msglevel ,
. get_wol = asix_get_wol ,
. set_wol = asix_set_wol ,
. get_eeprom_len = asix_get_eeprom_len ,
. get_eeprom = asix_get_eeprom ,
2012-07-19 04:23:07 +04:00
. set_eeprom = asix_set_eeprom ,
2006-10-09 02:08:01 +04:00
. nway_reset = usbnet_nway_reset ,
2021-04-06 02:13:41 +03:00
. get_link_ksettings = usbnet_get_link_ksettings_mii ,
. set_link_ksettings = usbnet_set_link_ksettings_mii ,
2006-07-29 18:12:50 +04:00
} ;
static int marvell_phy_init ( struct usbnet * dev )
2005-08-31 20:53:10 +04:00
{
2006-07-29 18:12:50 +04:00
struct asix_data * data = ( struct asix_data * ) & dev - > data ;
u16 reg ;
2005-08-31 20:53:10 +04:00
2010-02-17 13:30:23 +03:00
netdev_dbg ( dev - > net , " marvell_phy_init() \n " ) ;
2005-08-31 20:53:10 +04:00
2006-07-29 18:12:50 +04:00
reg = asix_mdio_read ( dev - > net , dev - > mii . phy_id , MII_MARVELL_STATUS ) ;
2010-02-17 13:30:23 +03:00
netdev_dbg ( dev - > net , " MII_MARVELL_STATUS = 0x%04x \n " , reg ) ;
2005-08-31 20:53:10 +04:00
2006-07-29 18:12:50 +04:00
asix_mdio_write ( dev - > net , dev - > mii . phy_id , MII_MARVELL_CTRL ,
MARVELL_CTRL_RXDELAY | MARVELL_CTRL_TXDELAY ) ;
2005-08-31 20:53:10 +04:00
2006-07-29 18:12:50 +04:00
if ( data - > ledmode ) {
reg = asix_mdio_read ( dev - > net , dev - > mii . phy_id ,
MII_MARVELL_LED_CTRL ) ;
2010-02-17 13:30:23 +03:00
netdev_dbg ( dev - > net , " MII_MARVELL_LED_CTRL (1) = 0x%04x \n " , reg ) ;
2005-08-31 20:53:10 +04:00
2006-07-29 18:12:50 +04:00
reg & = 0xf8ff ;
reg | = ( 1 + 0x0100 ) ;
asix_mdio_write ( dev - > net , dev - > mii . phy_id ,
MII_MARVELL_LED_CTRL , reg ) ;
2005-08-31 20:53:10 +04:00
2006-07-29 18:12:50 +04:00
reg = asix_mdio_read ( dev - > net , dev - > mii . phy_id ,
MII_MARVELL_LED_CTRL ) ;
2010-02-17 13:30:23 +03:00
netdev_dbg ( dev - > net , " MII_MARVELL_LED_CTRL (2) = 0x%04x \n " , reg ) ;
2006-07-29 18:12:50 +04:00
reg & = 0xfc0f ;
}
2005-08-31 20:53:10 +04:00
2006-07-29 18:12:50 +04:00
return 0 ;
}
2011-10-04 13:55:17 +04:00
static int rtl8211cl_phy_init ( struct usbnet * dev )
{
struct asix_data * data = ( struct asix_data * ) & dev - > data ;
netdev_dbg ( dev - > net , " rtl8211cl_phy_init() \n " ) ;
asix_mdio_write ( dev - > net , dev - > mii . phy_id , 0x1f , 0x0005 ) ;
asix_mdio_write ( dev - > net , dev - > mii . phy_id , 0x0c , 0 ) ;
asix_mdio_write ( dev - > net , dev - > mii . phy_id , 0x01 ,
asix_mdio_read ( dev - > net , dev - > mii . phy_id , 0x01 ) | 0x0080 ) ;
asix_mdio_write ( dev - > net , dev - > mii . phy_id , 0x1f , 0 ) ;
if ( data - > ledmode = = 12 ) {
asix_mdio_write ( dev - > net , dev - > mii . phy_id , 0x1f , 0x0002 ) ;
asix_mdio_write ( dev - > net , dev - > mii . phy_id , 0x1a , 0x00cb ) ;
asix_mdio_write ( dev - > net , dev - > mii . phy_id , 0x1f , 0 ) ;
}
return 0 ;
}
2006-07-29 18:12:50 +04:00
static int marvell_led_status ( struct usbnet * dev , u16 speed )
{
u16 reg = asix_mdio_read ( dev - > net , dev - > mii . phy_id , MARVELL_LED_MANUAL ) ;
2010-02-17 13:30:23 +03:00
netdev_dbg ( dev - > net , " marvell_led_status() read 0x%04x \n " , reg ) ;
2006-07-29 18:12:50 +04:00
/* Clear out the center LED bits - 0x03F0 */
reg & = 0xfc0f ;
switch ( speed ) {
case SPEED_1000 :
reg | = 0x03e0 ;
break ;
case SPEED_100 :
reg | = 0x03b0 ;
break ;
default :
reg | = 0x02f0 ;
2005-08-31 20:53:10 +04:00
}
2010-02-17 13:30:23 +03:00
netdev_dbg ( dev - > net , " marvell_led_status() writing 0x%04x \n " , reg ) ;
2006-07-29 18:12:50 +04:00
asix_mdio_write ( dev - > net , dev - > mii . phy_id , MARVELL_LED_MANUAL , reg ) ;
return 0 ;
}
2011-10-04 13:55:17 +04:00
static int ax88178_reset ( struct usbnet * dev )
{
struct asix_data * data = ( struct asix_data * ) & dev - > data ;
int ret ;
__le16 eeprom ;
u8 status ;
int gpio0 = 0 ;
2011-11-15 11:12:42 +04:00
u32 phyid ;
2011-10-04 13:55:17 +04:00
2016-08-29 16:32:15 +03:00
asix_read_cmd ( dev , AX_CMD_READ_GPIOS , 0 , 0 , 1 , & status , 0 ) ;
2012-09-19 13:46:14 +04:00
netdev_dbg ( dev - > net , " GPIO Status: 0x%04x \n " , status ) ;
2011-10-04 13:55:17 +04:00
2016-08-29 16:32:15 +03:00
asix_write_cmd ( dev , AX_CMD_WRITE_ENABLE , 0 , 0 , 0 , NULL , 0 ) ;
asix_read_cmd ( dev , AX_CMD_READ_EEPROM , 0x0017 , 0 , 2 , & eeprom , 0 ) ;
asix_write_cmd ( dev , AX_CMD_WRITE_DISABLE , 0 , 0 , 0 , NULL , 0 ) ;
2011-10-04 13:55:17 +04:00
2012-09-19 13:46:14 +04:00
netdev_dbg ( dev - > net , " EEPROM index 0x17 is 0x%04x \n " , eeprom ) ;
2011-10-04 13:55:17 +04:00
if ( eeprom = = cpu_to_le16 ( 0xffff ) ) {
data - > phymode = PHY_MODE_MARVELL ;
data - > ledmode = 0 ;
gpio0 = 1 ;
} else {
2011-11-15 11:12:42 +04:00
data - > phymode = le16_to_cpu ( eeprom ) & 0x7F ;
2011-10-04 13:55:17 +04:00
data - > ledmode = le16_to_cpu ( eeprom ) > > 8 ;
gpio0 = ( le16_to_cpu ( eeprom ) & 0x80 ) ? 0 : 1 ;
}
2012-09-19 13:46:14 +04:00
netdev_dbg ( dev - > net , " GPIO0: %d, PhyMode: %d \n " , gpio0 , data - > phymode ) ;
2011-10-04 13:55:17 +04:00
2011-11-15 11:12:42 +04:00
/* Power up external GigaPHY through AX88178 GPIO pin */
2016-08-29 16:32:15 +03:00
asix_write_gpio ( dev , AX_GPIO_RSE | AX_GPIO_GPO_1 |
AX_GPIO_GPO1EN , 40 , 0 ) ;
2011-10-04 13:55:17 +04:00
if ( ( le16_to_cpu ( eeprom ) > > 8 ) ! = 1 ) {
2016-08-29 16:32:15 +03:00
asix_write_gpio ( dev , 0x003c , 30 , 0 ) ;
asix_write_gpio ( dev , 0x001c , 300 , 0 ) ;
asix_write_gpio ( dev , 0x003c , 30 , 0 ) ;
2011-10-04 13:55:17 +04:00
} else {
2012-09-19 13:46:14 +04:00
netdev_dbg ( dev - > net , " gpio phymode == 1 path \n " ) ;
2016-08-29 16:32:15 +03:00
asix_write_gpio ( dev , AX_GPIO_GPO1EN , 30 , 0 ) ;
asix_write_gpio ( dev , AX_GPIO_GPO1EN | AX_GPIO_GPO_1 , 30 , 0 ) ;
2011-10-04 13:55:17 +04:00
}
2011-11-15 11:12:42 +04:00
/* Read PHYID register *AFTER* powering up PHY */
phyid = asix_get_phyid ( dev ) ;
2012-09-19 13:46:14 +04:00
netdev_dbg ( dev - > net , " PHYID=0x%08x \n " , phyid ) ;
2011-11-15 11:12:42 +04:00
/* Set AX88178 to enable MII/GMII/RGMII interface for external PHY */
2016-08-29 16:32:15 +03:00
asix_write_cmd ( dev , AX_CMD_SW_PHY_SELECT , 0 , 0 , 0 , NULL , 0 ) ;
2011-11-15 11:12:42 +04:00
2016-08-29 16:32:15 +03:00
asix_sw_reset ( dev , 0 , 0 ) ;
2011-10-04 13:55:17 +04:00
msleep ( 150 ) ;
2016-08-29 16:32:15 +03:00
asix_sw_reset ( dev , AX_SWRESET_PRL | AX_SWRESET_IPPD , 0 ) ;
2011-10-04 13:55:17 +04:00
msleep ( 150 ) ;
2016-08-29 16:32:15 +03:00
asix_write_rx_ctl ( dev , 0 , 0 ) ;
2011-10-04 13:55:17 +04:00
if ( data - > phymode = = PHY_MODE_MARVELL ) {
marvell_phy_init ( dev ) ;
msleep ( 60 ) ;
} else if ( data - > phymode = = PHY_MODE_RTL8211CL )
rtl8211cl_phy_init ( dev ) ;
2016-08-29 16:32:18 +03:00
asix_phy_reset ( dev , BMCR_RESET | BMCR_ANENABLE ) ;
2011-10-04 13:55:17 +04:00
asix_mdio_write ( dev - > net , dev - > mii . phy_id , MII_ADVERTISE ,
ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP ) ;
asix_mdio_write ( dev - > net , dev - > mii . phy_id , MII_CTRL1000 ,
ADVERTISE_1000FULL ) ;
2016-08-29 16:32:19 +03:00
asix_write_medium_mode ( dev , AX88178_MEDIUM_DEFAULT , 0 ) ;
2011-10-04 13:55:17 +04:00
mii_nway_restart ( & dev - > mii ) ;
2012-01-10 10:40:23 +04:00
/* Rewrite MAC address */
memcpy ( data - > mac_addr , dev - > net - > dev_addr , ETH_ALEN ) ;
ret = asix_write_cmd ( dev , AX_CMD_WRITE_NODE_ID , 0 , 0 , ETH_ALEN ,
2016-08-29 16:32:15 +03:00
data - > mac_addr , 0 ) ;
2012-01-10 10:40:23 +04:00
if ( ret < 0 )
return ret ;
2016-08-29 16:32:15 +03:00
ret = asix_write_rx_ctl ( dev , AX_DEFAULT_RX_CTL , 0 ) ;
2011-10-04 13:55:18 +04:00
if ( ret < 0 )
return ret ;
2011-10-04 13:55:17 +04:00
return 0 ;
}
2006-07-29 18:12:50 +04:00
static int ax88178_link_reset ( struct usbnet * dev )
{
u16 mode ;
2011-04-27 22:32:38 +04:00
struct ethtool_cmd ecmd = { . cmd = ETHTOOL_GSET } ;
2006-07-29 18:12:50 +04:00
struct asix_data * data = ( struct asix_data * ) & dev - > data ;
2011-04-27 22:32:38 +04:00
u32 speed ;
2006-07-29 18:12:50 +04:00
2010-02-17 13:30:23 +03:00
netdev_dbg ( dev - > net , " ax88178_link_reset() \n " ) ;
2006-07-29 18:12:50 +04:00
mii_check_media ( & dev - > mii , 1 , 1 ) ;
mii_ethtool_gset ( & dev - > mii , & ecmd ) ;
mode = AX88178_MEDIUM_DEFAULT ;
2011-04-27 22:32:38 +04:00
speed = ethtool_cmd_speed ( & ecmd ) ;
2006-07-29 18:12:50 +04:00
2011-04-27 22:32:38 +04:00
if ( speed = = SPEED_1000 )
2008-11-20 12:48:46 +03:00
mode | = AX_MEDIUM_GM ;
2011-04-27 22:32:38 +04:00
else if ( speed = = SPEED_100 )
2006-07-29 18:12:50 +04:00
mode | = AX_MEDIUM_PS ;
else
mode & = ~ ( AX_MEDIUM_PS | AX_MEDIUM_GM ) ;
2008-11-20 12:48:46 +03:00
mode | = AX_MEDIUM_ENCK ;
2006-07-29 18:12:50 +04:00
if ( ecmd . duplex = = DUPLEX_FULL )
mode | = AX_MEDIUM_FD ;
else
mode & = ~ AX_MEDIUM_FD ;
2011-04-27 22:32:38 +04:00
netdev_dbg ( dev - > net , " ax88178_link_reset() speed: %u duplex: %d setting mode to 0x%04x \n " ,
speed , ecmd . duplex , mode ) ;
2006-07-29 18:12:50 +04:00
2016-08-29 16:32:15 +03:00
asix_write_medium_mode ( dev , mode , 0 ) ;
2006-07-29 18:12:50 +04:00
if ( data - > phymode = = PHY_MODE_MARVELL & & data - > ledmode )
2011-04-27 22:32:38 +04:00
marvell_led_status ( dev , speed ) ;
2006-07-29 18:12:50 +04:00
return 0 ;
}
static void ax88178_set_mfb ( struct usbnet * dev )
{
u16 mfb = AX_RX_CTL_MFB_16384 ;
u16 rxctl ;
u16 medium ;
int old_rx_urb_size = dev - > rx_urb_size ;
if ( dev - > hard_mtu < 2048 ) {
dev - > rx_urb_size = 2048 ;
mfb = AX_RX_CTL_MFB_2048 ;
} else if ( dev - > hard_mtu < 4096 ) {
dev - > rx_urb_size = 4096 ;
mfb = AX_RX_CTL_MFB_4096 ;
} else if ( dev - > hard_mtu < 8192 ) {
dev - > rx_urb_size = 8192 ;
mfb = AX_RX_CTL_MFB_8192 ;
} else if ( dev - > hard_mtu < 16384 ) {
dev - > rx_urb_size = 16384 ;
mfb = AX_RX_CTL_MFB_16384 ;
2005-08-31 20:53:10 +04:00
}
2006-07-29 18:12:50 +04:00
2016-08-29 16:32:15 +03:00
rxctl = asix_read_rx_ctl ( dev , 0 ) ;
asix_write_rx_ctl ( dev , ( rxctl & ~ AX_RX_CTL_MFB_16384 ) | mfb , 0 ) ;
2006-07-29 18:12:50 +04:00
2016-08-29 16:32:15 +03:00
medium = asix_read_medium_status ( dev , 0 ) ;
2006-07-29 18:12:50 +04:00
if ( dev - > net - > mtu > 1500 )
medium | = AX_MEDIUM_JFE ;
else
medium & = ~ AX_MEDIUM_JFE ;
2016-08-29 16:32:15 +03:00
asix_write_medium_mode ( dev , medium , 0 ) ;
2006-07-29 18:12:50 +04:00
if ( dev - > rx_urb_size > old_rx_urb_size )
usbnet_unlink_rx_urbs ( dev ) ;
2005-08-31 20:53:10 +04:00
}
2006-07-29 18:12:50 +04:00
static int ax88178_change_mtu ( struct net_device * net , int new_mtu )
2005-08-31 20:53:10 +04:00
{
2006-07-29 18:12:50 +04:00
struct usbnet * dev = netdev_priv ( net ) ;
int ll_mtu = new_mtu + net - > hard_header_len + 4 ;
2005-08-31 20:53:10 +04:00
2010-02-17 13:30:23 +03:00
netdev_dbg ( dev - > net , " ax88178_change_mtu() new_mtu=%d \n " , new_mtu ) ;
2005-08-31 20:53:10 +04:00
2006-07-29 18:12:50 +04:00
if ( ( ll_mtu % dev - > maxpacket ) = = 0 )
return - EDOM ;
net - > mtu = new_mtu ;
dev - > hard_mtu = net - > mtu + net - > hard_header_len ;
ax88178_set_mfb ( dev ) ;
USBNET: centralize computing of max rx/tx qlen
This patch centralizes computing of max rx/tx qlen, because:
- RX_QLEN()/TX_QLEN() is called in hot path
- computing depends on device's usb speed, now we have ls/fs, hs, ss,
so more checks need to be involved
- in fact, max rx/tx qlen should not only depend on device USB
speed, but also depend on ethernet link speed, so we need to
consider that in future.
- if SG support is done, max tx qlen may need change too
Generally, hard_mtu and rx_urb_size are changed in bind(), reset()
and link_reset() callback, and change mtu network operation, this
patches introduces the API of usbnet_update_max_qlen(), and calls
it in above path.
Signed-off-by: Ming Lei <ming.lei@canonical.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2013-07-25 09:47:53 +04:00
/* max qlen depend on hard_mtu and rx_urb_size */
usbnet_update_max_qlen ( dev ) ;
2006-07-29 18:12:50 +04:00
return 0 ;
}
2009-03-20 22:35:55 +03:00
static const struct net_device_ops ax88178_netdev_ops = {
. ndo_open = usbnet_open ,
. ndo_stop = usbnet_stop ,
. ndo_start_xmit = usbnet_start_xmit ,
. ndo_tx_timeout = usbnet_tx_timeout ,
2020-11-10 22:51:03 +03:00
. ndo_get_stats64 = dev_get_tstats64 ,
2010-03-09 15:24:38 +03:00
. ndo_set_mac_address = asix_set_mac_address ,
2009-03-20 22:35:55 +03:00
. ndo_validate_addr = eth_validate_addr ,
2011-08-16 10:29:01 +04:00
. ndo_set_rx_mode = asix_set_multicast ,
2009-03-20 22:35:55 +03:00
. ndo_do_ioctl = asix_ioctl ,
. ndo_change_mtu = ax88178_change_mtu ,
} ;
2006-07-29 18:12:50 +04:00
static int ax88178_bind ( struct usbnet * dev , struct usb_interface * intf )
{
int ret ;
2019-07-02 03:10:08 +03:00
u8 buf [ ETH_ALEN ] = { 0 } ;
2006-07-29 18:12:50 +04:00
usbnet_get_endpoints ( dev , intf ) ;
/* Get the MAC address */
2016-08-29 16:32:15 +03:00
ret = asix_read_cmd ( dev , AX_CMD_READ_NODE_ID , 0 , 0 , ETH_ALEN , buf , 0 ) ;
2011-10-04 13:55:18 +04:00
if ( ret < 0 ) {
2012-09-19 13:46:14 +04:00
netdev_dbg ( dev - > net , " Failed to read MAC address: %d \n " , ret ) ;
2011-10-04 13:55:18 +04:00
return ret ;
2005-08-31 20:53:10 +04:00
}
2012-11-22 01:35:17 +04:00
asix_set_netdev_dev_addr ( dev , buf ) ;
2005-08-31 20:53:10 +04:00
2006-07-29 18:12:50 +04:00
/* Initialize MII structure */
dev - > mii . dev = dev - > net ;
dev - > mii . mdio_read = asix_mdio_read ;
dev - > mii . mdio_write = asix_mdio_write ;
dev - > mii . phy_id_mask = 0x1f ;
dev - > mii . reg_num_mask = 0xff ;
dev - > mii . supports_gmii = 1 ;
2021-06-07 11:27:21 +03:00
dev - > mii . phy_id = asix_read_phy_addr ( dev , true ) ;
if ( dev - > mii . phy_id < 0 )
return dev - > mii . phy_id ;
2009-03-20 22:35:55 +03:00
dev - > net - > netdev_ops = & ax88178_netdev_ops ;
2006-07-29 18:12:50 +04:00
dev - > net - > ethtool_ops = & ax88178_ethtool_ops ;
2016-10-20 20:55:17 +03:00
dev - > net - > max_mtu = 16384 - ( dev - > net - > hard_header_len + 4 ) ;
2005-08-31 20:53:10 +04:00
2011-11-15 11:12:42 +04:00
/* Blink LEDS so users know driver saw dongle */
2016-08-29 16:32:15 +03:00
asix_sw_reset ( dev , 0 , 0 ) ;
2011-11-15 11:12:42 +04:00
msleep ( 150 ) ;
2005-08-31 20:53:10 +04:00
2016-08-29 16:32:15 +03:00
asix_sw_reset ( dev , AX_SWRESET_PRL | AX_SWRESET_IPPD , 0 ) ;
2011-11-15 11:12:42 +04:00
msleep ( 150 ) ;
2006-07-29 18:12:50 +04:00
/* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
if ( dev - > driver_info - > flags & FLAG_FRAMING_AX ) {
/* hard_mtu is still the default - the device does not support
jumbo eth frames */
dev - > rx_urb_size = 2048 ;
}
2013-01-16 08:24:07 +04:00
dev - > driver_priv = kzalloc ( sizeof ( struct asix_common_private ) , GFP_KERNEL ) ;
if ( ! dev - > driver_priv )
return - ENOMEM ;
2011-10-04 13:55:18 +04:00
return 0 ;
2005-08-31 20:53:10 +04:00
}
static const struct driver_info ax8817x_info = {
. description = " ASIX AX8817x USB 2.0 Ethernet " ,
2006-03-29 05:15:42 +04:00
. bind = ax88172_bind ,
. status = asix_status ,
2005-08-31 20:53:10 +04:00
. link_reset = ax88172_link_reset ,
. reset = ax88172_link_reset ,
2009-11-04 18:29:52 +03:00
. flags = FLAG_ETHER | FLAG_LINK_INTR ,
2005-08-31 20:53:10 +04:00
. data = 0x00130103 ,
} ;
static const struct driver_info dlink_dub_e100_info = {
. description = " DLink DUB-E100 USB Ethernet " ,
2006-03-29 05:15:42 +04:00
. bind = ax88172_bind ,
. status = asix_status ,
2005-08-31 20:53:10 +04:00
. link_reset = ax88172_link_reset ,
. reset = ax88172_link_reset ,
2009-11-04 18:29:52 +03:00
. flags = FLAG_ETHER | FLAG_LINK_INTR ,
2005-08-31 20:53:10 +04:00
. data = 0x009f9d9f ,
} ;
static const struct driver_info netgear_fa120_info = {
. description = " Netgear FA-120 USB Ethernet " ,
2006-03-29 05:15:42 +04:00
. bind = ax88172_bind ,
. status = asix_status ,
2005-08-31 20:53:10 +04:00
. link_reset = ax88172_link_reset ,
. reset = ax88172_link_reset ,
2009-11-04 18:29:52 +03:00
. flags = FLAG_ETHER | FLAG_LINK_INTR ,
2005-08-31 20:53:10 +04:00
. data = 0x00130103 ,
} ;
static const struct driver_info hawking_uf200_info = {
. description = " Hawking UF200 USB Ethernet " ,
2006-03-29 05:15:42 +04:00
. bind = ax88172_bind ,
. status = asix_status ,
2005-08-31 20:53:10 +04:00
. link_reset = ax88172_link_reset ,
. reset = ax88172_link_reset ,
2009-11-04 18:29:52 +03:00
. flags = FLAG_ETHER | FLAG_LINK_INTR ,
2005-08-31 20:53:10 +04:00
. data = 0x001f1d1f ,
} ;
static const struct driver_info ax88772_info = {
. description = " ASIX AX88772 USB 2.0 Ethernet " ,
. bind = ax88772_bind ,
2013-01-16 08:24:07 +04:00
. unbind = ax88772_unbind ,
2006-03-29 05:15:42 +04:00
. status = asix_status ,
2016-08-29 16:32:15 +03:00
. reset = ax88772_reset ,
2021-06-07 11:27:23 +03:00
. stop = ax88772_stop ,
2012-03-15 00:18:32 +04:00
. flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | FLAG_MULTI_PACKET ,
2013-01-16 08:24:07 +04:00
. rx_fixup = asix_rx_fixup_common ,
2006-07-29 18:12:50 +04:00
. tx_fixup = asix_tx_fixup ,
} ;
2013-01-16 08:24:06 +04:00
static const struct driver_info ax88772b_info = {
. description = " ASIX AX88772B USB 2.0 Ethernet " ,
. bind = ax88772_bind ,
2013-01-16 08:24:07 +04:00
. unbind = ax88772_unbind ,
2013-01-16 08:24:06 +04:00
. status = asix_status ,
. reset = ax88772_reset ,
. flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
FLAG_MULTI_PACKET ,
2013-01-16 08:24:07 +04:00
. rx_fixup = asix_rx_fixup_common ,
2013-01-16 08:24:06 +04:00
. tx_fixup = asix_tx_fixup ,
. data = FLAG_EEPROM_MAC ,
} ;
2006-07-29 18:12:50 +04:00
static const struct driver_info ax88178_info = {
. description = " ASIX AX88178 USB 2.0 Ethernet " ,
. bind = ax88178_bind ,
2013-01-16 08:24:07 +04:00
. unbind = ax88772_unbind ,
2006-07-29 18:12:50 +04:00
. status = asix_status ,
. link_reset = ax88178_link_reset ,
2011-10-04 13:55:17 +04:00
. reset = ax88178_reset ,
2014-02-13 22:30:39 +04:00
. flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
FLAG_MULTI_PACKET ,
2013-01-16 08:24:07 +04:00
. rx_fixup = asix_rx_fixup_common ,
2006-07-29 18:12:50 +04:00
. tx_fixup = asix_tx_fixup ,
2005-08-31 20:53:10 +04:00
} ;
2013-02-27 08:32:36 +04:00
/*
* USBLINK 20F 9 " USB 2.0 LAN " USB ethernet adapter , typically found in
* no - name packaging .
* USB device strings are :
* 1 : Manufacturer : USBLINK
* 2 : Product : HG20F9 USB2 .0
* 3 : Serial : 000003
* Appears to be compatible with Asix 88772 B .
*/
static const struct driver_info hg20f9_info = {
. description = " HG20F9 USB 2.0 Ethernet " ,
. bind = ax88772_bind ,
. unbind = ax88772_unbind ,
. status = asix_status ,
. reset = ax88772_reset ,
. flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
FLAG_MULTI_PACKET ,
. rx_fixup = asix_rx_fixup_common ,
. tx_fixup = asix_tx_fixup ,
. data = FLAG_EEPROM_MAC ,
} ;
2005-08-31 20:53:10 +04:00
static const struct usb_device_id products [ ] = {
{
// Linksys USB200M
USB_DEVICE ( 0x077b , 0x2226 ) ,
. driver_info = ( unsigned long ) & ax8817x_info ,
} , {
// Netgear FA120
USB_DEVICE ( 0x0846 , 0x1040 ) ,
. driver_info = ( unsigned long ) & netgear_fa120_info ,
} , {
// DLink DUB-E100
USB_DEVICE ( 0x2001 , 0x1a00 ) ,
. driver_info = ( unsigned long ) & dlink_dub_e100_info ,
} , {
// Intellinet, ST Lab USB Ethernet
USB_DEVICE ( 0x0b95 , 0x1720 ) ,
. driver_info = ( unsigned long ) & ax8817x_info ,
} , {
// Hawking UF200, TrendNet TU2-ET100
USB_DEVICE ( 0x07b8 , 0x420a ) ,
. driver_info = ( unsigned long ) & hawking_uf200_info ,
} , {
2007-02-20 16:02:24 +03:00
// Billionton Systems, USB2AR
USB_DEVICE ( 0x08dd , 0x90ff ) ,
. driver_info = ( unsigned long ) & ax8817x_info ,
2015-10-15 21:00:21 +03:00
} , {
// Billionton Systems, GUSB2AM-1G-B
USB_DEVICE ( 0x08dd , 0x0114 ) ,
. driver_info = ( unsigned long ) & ax88178_info ,
2005-08-31 20:53:10 +04:00
} , {
// ATEN UC210T
USB_DEVICE ( 0x0557 , 0x2009 ) ,
. driver_info = ( unsigned long ) & ax8817x_info ,
} , {
// Buffalo LUA-U2-KTX
USB_DEVICE ( 0x0411 , 0x003d ) ,
. driver_info = ( unsigned long ) & ax8817x_info ,
2008-05-07 07:42:35 +04:00
} , {
// Buffalo LUA-U2-GT 10/100/1000
USB_DEVICE ( 0x0411 , 0x006e ) ,
. driver_info = ( unsigned long ) & ax88178_info ,
2005-08-31 20:53:10 +04:00
} , {
// Sitecom LN-029 "USB 2.0 10/100 Ethernet adapter"
USB_DEVICE ( 0x6189 , 0x182d ) ,
. driver_info = ( unsigned long ) & ax8817x_info ,
2012-03-09 02:44:03 +04:00
} , {
// Sitecom LN-031 "USB 2.0 10/100/1000 Ethernet adapter"
USB_DEVICE ( 0x0df6 , 0x0056 ) ,
. driver_info = ( unsigned long ) & ax88178_info ,
2015-02-26 02:58:12 +03:00
} , {
// Sitecom LN-028 "USB 2.0 10/100/1000 Ethernet adapter"
USB_DEVICE ( 0x0df6 , 0x061c ) ,
. driver_info = ( unsigned long ) & ax88178_info ,
2005-08-31 20:53:10 +04:00
} , {
// corega FEther USB2-TX
USB_DEVICE ( 0x07aa , 0x0017 ) ,
. driver_info = ( unsigned long ) & ax8817x_info ,
} , {
// Surecom EP-1427X-2
USB_DEVICE ( 0x1189 , 0x0893 ) ,
. driver_info = ( unsigned long ) & ax8817x_info ,
} , {
// goodway corp usb gwusb2e
USB_DEVICE ( 0x1631 , 0x6200 ) ,
. driver_info = ( unsigned long ) & ax8817x_info ,
2007-02-20 16:02:24 +03:00
} , {
// JVC MP-PRX1 Port Replicator
USB_DEVICE ( 0x04f1 , 0x3008 ) ,
. driver_info = ( unsigned long ) & ax8817x_info ,
2012-09-28 23:58:44 +04:00
} , {
// Lenovo U2L100P 10/100
USB_DEVICE ( 0x17ef , 0x7203 ) ,
2016-08-29 16:32:15 +03:00
. driver_info = ( unsigned long ) & ax88772b_info ,
2011-07-20 09:57:04 +04:00
} , {
// ASIX AX88772B 10/100
USB_DEVICE ( 0x0b95 , 0x772b ) ,
2013-01-16 08:24:06 +04:00
. driver_info = ( unsigned long ) & ax88772b_info ,
2005-08-31 20:53:10 +04:00
} , {
// ASIX AX88772 10/100
2007-02-20 16:02:24 +03:00
USB_DEVICE ( 0x0b95 , 0x7720 ) ,
. driver_info = ( unsigned long ) & ax88772_info ,
2006-05-18 12:13:17 +04:00
} , {
// ASIX AX88178 10/100/1000
USB_DEVICE ( 0x0b95 , 0x1780 ) ,
2006-07-29 18:12:50 +04:00
. driver_info = ( unsigned long ) & ax88178_info ,
2010-12-15 15:16:30 +03:00
} , {
// Logitec LAN-GTJ/U2A
USB_DEVICE ( 0x0789 , 0x0160 ) ,
. driver_info = ( unsigned long ) & ax88178_info ,
2005-12-19 21:58:38 +03:00
} , {
// Linksys USB200M Rev 2
USB_DEVICE ( 0x13b1 , 0x0018 ) ,
. driver_info = ( unsigned long ) & ax88772_info ,
2006-01-05 22:39:49 +03:00
} , {
// 0Q0 cable ethernet
USB_DEVICE ( 0x1557 , 0x7720 ) ,
. driver_info = ( unsigned long ) & ax88772_info ,
2006-07-29 18:12:50 +04:00
} , {
// DLink DUB-E100 H/W Ver B1
USB_DEVICE ( 0x07d1 , 0x3c05 ) ,
. driver_info = ( unsigned long ) & ax88772_info ,
2006-09-21 16:09:29 +04:00
} , {
// DLink DUB-E100 H/W Ver B1 Alternate
USB_DEVICE ( 0x2001 , 0x3c05 ) ,
. driver_info = ( unsigned long ) & ax88772_info ,
2012-09-18 01:50:57 +04:00
} , {
// DLink DUB-E100 H/W Ver C1
USB_DEVICE ( 0x2001 , 0x1a02 ) ,
. driver_info = ( unsigned long ) & ax88772_info ,
2006-07-29 18:12:50 +04:00
} , {
// Linksys USB1000
USB_DEVICE ( 0x1737 , 0x0039 ) ,
. driver_info = ( unsigned long ) & ax88178_info ,
2007-01-26 16:57:38 +03:00
} , {
// IO-DATA ETG-US2
USB_DEVICE ( 0x04bb , 0x0930 ) ,
. driver_info = ( unsigned long ) & ax88178_info ,
2007-05-23 15:33:17 +04:00
} , {
// Belkin F5D5055
USB_DEVICE ( 0x050d , 0x5055 ) ,
. driver_info = ( unsigned long ) & ax88178_info ,
2008-05-15 04:04:13 +04:00
} , {
// Apple USB Ethernet Adapter
USB_DEVICE ( 0x05ac , 0x1402 ) ,
. driver_info = ( unsigned long ) & ax88772_info ,
2008-11-11 21:02:53 +03:00
} , {
// Cables-to-Go USB Ethernet Adapter
USB_DEVICE ( 0x0b95 , 0x772a ) ,
. driver_info = ( unsigned long ) & ax88772_info ,
2009-02-25 10:52:24 +03:00
} , {
// ABOCOM for pci
USB_DEVICE ( 0x14ea , 0xab11 ) ,
. driver_info = ( unsigned long ) & ax88178_info ,
} , {
// ASIX 88772a
USB_DEVICE ( 0x0db0 , 0xa877 ) ,
. driver_info = ( unsigned long ) & ax88772_info ,
2011-12-16 14:49:22 +04:00
} , {
// Asus USB Ethernet Adapter
USB_DEVICE ( 0x0b95 , 0x7e2b ) ,
2016-08-29 16:32:15 +03:00
. driver_info = ( unsigned long ) & ax88772b_info ,
2012-07-13 09:26:31 +04:00
} , {
/* ASIX 88172a demo board */
USB_DEVICE ( 0x0b95 , 0x172a ) ,
. driver_info = ( unsigned long ) & ax88172a_info ,
2013-02-27 08:32:36 +04:00
} , {
/*
* USBLINK HG20F9 " USB 2.0 LAN "
* Appears to have gazumped Linksys ' s manufacturer ID but
* doesn ' t ( yet ) conflict with any known Linksys product .
*/
USB_DEVICE ( 0x066b , 0x20f9 ) ,
. driver_info = ( unsigned long ) & hg20f9_info ,
2005-08-31 20:53:10 +04:00
} ,
{ } , // END
} ;
MODULE_DEVICE_TABLE ( usb , products ) ;
static struct usb_driver asix_driver = {
2011-10-04 13:55:18 +04:00
. name = DRIVER_NAME ,
2005-08-31 20:53:10 +04:00
. id_table = products ,
. probe = usbnet_probe ,
2016-08-29 16:32:15 +03:00
. suspend = asix_suspend ,
. resume = asix_resume ,
2017-01-03 12:22:20 +03:00
. reset_resume = asix_resume ,
2005-08-31 20:53:10 +04:00
. disconnect = usbnet_disconnect ,
2007-08-03 15:52:19 +04:00
. supports_autosuspend = 1 ,
2012-04-23 21:08:51 +04:00
. disable_hub_initiated_lpm = 1 ,
2005-08-31 20:53:10 +04:00
} ;
2011-11-18 21:44:20 +04:00
module_usb_driver ( asix_driver ) ;
2005-08-31 20:53:10 +04:00
MODULE_AUTHOR ( " David Hollis " ) ;
2011-10-04 13:55:16 +04:00
MODULE_VERSION ( DRIVER_VERSION ) ;
2005-08-31 20:53:10 +04:00
MODULE_DESCRIPTION ( " ASIX AX8817X based USB 2.0 Ethernet Devices " ) ;
MODULE_LICENSE ( " GPL " ) ;