117364b80SDmitry Bezrukov // SPDX-License-Identifier: GPL-2.0-or-later 217364b80SDmitry Bezrukov /* Aquantia Corp. Aquantia AQtion USB to 5GbE Controller 317364b80SDmitry Bezrukov * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com> 417364b80SDmitry Bezrukov * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net> 517364b80SDmitry Bezrukov * Copyright (C) 2002-2003 TiVo Inc. 617364b80SDmitry Bezrukov * Copyright (C) 2017-2018 ASIX 717364b80SDmitry Bezrukov * Copyright (C) 2018 Aquantia Corp. 817364b80SDmitry Bezrukov */ 917364b80SDmitry Bezrukov 1017364b80SDmitry Bezrukov #include <linux/module.h> 1117364b80SDmitry Bezrukov #include <linux/netdevice.h> 12027e6f78SDmitry Bezrukov #include <linux/ethtool.h> 1317364b80SDmitry Bezrukov #include <linux/mii.h> 1417364b80SDmitry Bezrukov #include <linux/usb.h> 1559b04eeaSDmitry Bezrukov #include <linux/crc32.h> 16df2d59a2SDmitry Bezrukov #include <linux/if_vlan.h> 1717364b80SDmitry Bezrukov #include <linux/usb/cdc.h> 1817364b80SDmitry Bezrukov #include <linux/usb/usbnet.h> 19abbd8e7dSDmitry Bezrukov #include <linux/linkmode.h> 2017364b80SDmitry Bezrukov 21619fcb44SDmitry Bezrukov #include "aqc111.h" 22619fcb44SDmitry Bezrukov 23027e6f78SDmitry Bezrukov #define DRIVER_NAME "aqc111" 24027e6f78SDmitry Bezrukov 25619fcb44SDmitry Bezrukov static int aqc111_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, 26619fcb44SDmitry Bezrukov u16 index, u16 size, void *data) 27619fcb44SDmitry Bezrukov { 28619fcb44SDmitry Bezrukov int ret; 29619fcb44SDmitry Bezrukov 30619fcb44SDmitry Bezrukov ret = usbnet_read_cmd_nopm(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | 31619fcb44SDmitry Bezrukov USB_RECIP_DEVICE, value, index, data, size); 32619fcb44SDmitry Bezrukov 33619fcb44SDmitry Bezrukov if (unlikely(ret < 0)) 34619fcb44SDmitry Bezrukov netdev_warn(dev->net, 35619fcb44SDmitry Bezrukov "Failed to read(0x%x) reg index 0x%04x: %d\n", 36619fcb44SDmitry Bezrukov cmd, index, ret); 37619fcb44SDmitry Bezrukov 38619fcb44SDmitry Bezrukov return ret; 39619fcb44SDmitry Bezrukov } 40619fcb44SDmitry Bezrukov 41619fcb44SDmitry Bezrukov static int aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value, 42619fcb44SDmitry Bezrukov u16 index, u16 size, void *data) 43619fcb44SDmitry Bezrukov { 44619fcb44SDmitry Bezrukov int ret; 45619fcb44SDmitry Bezrukov 46619fcb44SDmitry Bezrukov ret = usbnet_read_cmd(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | 47619fcb44SDmitry Bezrukov USB_RECIP_DEVICE, value, index, data, size); 48619fcb44SDmitry Bezrukov 49619fcb44SDmitry Bezrukov if (unlikely(ret < 0)) 50619fcb44SDmitry Bezrukov netdev_warn(dev->net, 51619fcb44SDmitry Bezrukov "Failed to read(0x%x) reg index 0x%04x: %d\n", 52619fcb44SDmitry Bezrukov cmd, index, ret); 53619fcb44SDmitry Bezrukov 54619fcb44SDmitry Bezrukov return ret; 55619fcb44SDmitry Bezrukov } 56619fcb44SDmitry Bezrukov 57e58ba454SDmitry Bezrukov static int aqc111_read16_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, 58e58ba454SDmitry Bezrukov u16 index, u16 *data) 59e58ba454SDmitry Bezrukov { 60e58ba454SDmitry Bezrukov int ret = 0; 61e58ba454SDmitry Bezrukov 62e58ba454SDmitry Bezrukov ret = aqc111_read_cmd_nopm(dev, cmd, value, index, sizeof(*data), data); 63e58ba454SDmitry Bezrukov le16_to_cpus(data); 64e58ba454SDmitry Bezrukov 65e58ba454SDmitry Bezrukov return ret; 66e58ba454SDmitry Bezrukov } 67e58ba454SDmitry Bezrukov 68f3aa095aSDmitry Bezrukov static int aqc111_read16_cmd(struct usbnet *dev, u8 cmd, u16 value, 69f3aa095aSDmitry Bezrukov u16 index, u16 *data) 70f3aa095aSDmitry Bezrukov { 71f3aa095aSDmitry Bezrukov int ret = 0; 72f3aa095aSDmitry Bezrukov 73f3aa095aSDmitry Bezrukov ret = aqc111_read_cmd(dev, cmd, value, index, sizeof(*data), data); 74f3aa095aSDmitry Bezrukov le16_to_cpus(data); 75f3aa095aSDmitry Bezrukov 76f3aa095aSDmitry Bezrukov return ret; 77f3aa095aSDmitry Bezrukov } 78f3aa095aSDmitry Bezrukov 79619fcb44SDmitry Bezrukov static int __aqc111_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype, 80619fcb44SDmitry Bezrukov u16 value, u16 index, u16 size, const void *data) 81619fcb44SDmitry Bezrukov { 82619fcb44SDmitry Bezrukov int err = -ENOMEM; 83619fcb44SDmitry Bezrukov void *buf = NULL; 84619fcb44SDmitry Bezrukov 85619fcb44SDmitry Bezrukov netdev_dbg(dev->net, 86619fcb44SDmitry Bezrukov "%s cmd=%#x reqtype=%#x value=%#x index=%#x size=%d\n", 87619fcb44SDmitry Bezrukov __func__, cmd, reqtype, value, index, size); 88619fcb44SDmitry Bezrukov 89619fcb44SDmitry Bezrukov if (data) { 90619fcb44SDmitry Bezrukov buf = kmemdup(data, size, GFP_KERNEL); 91619fcb44SDmitry Bezrukov if (!buf) 92619fcb44SDmitry Bezrukov goto out; 93619fcb44SDmitry Bezrukov } 94619fcb44SDmitry Bezrukov 95619fcb44SDmitry Bezrukov err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), 96619fcb44SDmitry Bezrukov cmd, reqtype, value, index, buf, size, 97619fcb44SDmitry Bezrukov (cmd == AQ_PHY_POWER) ? AQ_USB_PHY_SET_TIMEOUT : 98619fcb44SDmitry Bezrukov AQ_USB_SET_TIMEOUT); 99619fcb44SDmitry Bezrukov 100619fcb44SDmitry Bezrukov if (unlikely(err < 0)) 101619fcb44SDmitry Bezrukov netdev_warn(dev->net, 102619fcb44SDmitry Bezrukov "Failed to write(0x%x) reg index 0x%04x: %d\n", 103619fcb44SDmitry Bezrukov cmd, index, err); 104619fcb44SDmitry Bezrukov kfree(buf); 105619fcb44SDmitry Bezrukov 106619fcb44SDmitry Bezrukov out: 107619fcb44SDmitry Bezrukov return err; 108619fcb44SDmitry Bezrukov } 109619fcb44SDmitry Bezrukov 110619fcb44SDmitry Bezrukov static int aqc111_write_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, 111619fcb44SDmitry Bezrukov u16 index, u16 size, void *data) 112619fcb44SDmitry Bezrukov { 113619fcb44SDmitry Bezrukov int ret; 114619fcb44SDmitry Bezrukov 115619fcb44SDmitry Bezrukov ret = __aqc111_write_cmd(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | 116619fcb44SDmitry Bezrukov USB_RECIP_DEVICE, value, index, size, data); 117619fcb44SDmitry Bezrukov 118619fcb44SDmitry Bezrukov return ret; 119619fcb44SDmitry Bezrukov } 120619fcb44SDmitry Bezrukov 121619fcb44SDmitry Bezrukov static int aqc111_write_cmd(struct usbnet *dev, u8 cmd, u16 value, 122619fcb44SDmitry Bezrukov u16 index, u16 size, void *data) 123619fcb44SDmitry Bezrukov { 124619fcb44SDmitry Bezrukov int ret; 125619fcb44SDmitry Bezrukov 126619fcb44SDmitry Bezrukov if (usb_autopm_get_interface(dev->intf) < 0) 127619fcb44SDmitry Bezrukov return -ENODEV; 128619fcb44SDmitry Bezrukov 129619fcb44SDmitry Bezrukov ret = __aqc111_write_cmd(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | 130619fcb44SDmitry Bezrukov USB_RECIP_DEVICE, value, index, size, data); 131619fcb44SDmitry Bezrukov 132619fcb44SDmitry Bezrukov usb_autopm_put_interface(dev->intf); 133619fcb44SDmitry Bezrukov 134619fcb44SDmitry Bezrukov return ret; 135619fcb44SDmitry Bezrukov } 136619fcb44SDmitry Bezrukov 137f3aa095aSDmitry Bezrukov static int aqc111_write16_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, 138f3aa095aSDmitry Bezrukov u16 index, u16 *data) 139f3aa095aSDmitry Bezrukov { 140f3aa095aSDmitry Bezrukov u16 tmp = *data; 141f3aa095aSDmitry Bezrukov 142f3aa095aSDmitry Bezrukov cpu_to_le16s(&tmp); 143f3aa095aSDmitry Bezrukov 144f3aa095aSDmitry Bezrukov return aqc111_write_cmd_nopm(dev, cmd, value, index, sizeof(tmp), &tmp); 145f3aa095aSDmitry Bezrukov } 146f3aa095aSDmitry Bezrukov 147f3aa095aSDmitry Bezrukov static int aqc111_write16_cmd(struct usbnet *dev, u8 cmd, u16 value, 148f3aa095aSDmitry Bezrukov u16 index, u16 *data) 149f3aa095aSDmitry Bezrukov { 150f3aa095aSDmitry Bezrukov u16 tmp = *data; 151f3aa095aSDmitry Bezrukov 152f3aa095aSDmitry Bezrukov cpu_to_le16s(&tmp); 153f3aa095aSDmitry Bezrukov 154f3aa095aSDmitry Bezrukov return aqc111_write_cmd(dev, cmd, value, index, sizeof(tmp), &tmp); 155f3aa095aSDmitry Bezrukov } 156f3aa095aSDmitry Bezrukov 15733cd597fSDmitry Bezrukov static int aqc111_write32_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, 15833cd597fSDmitry Bezrukov u16 index, u32 *data) 15933cd597fSDmitry Bezrukov { 16033cd597fSDmitry Bezrukov u32 tmp = *data; 16133cd597fSDmitry Bezrukov 16233cd597fSDmitry Bezrukov cpu_to_le32s(&tmp); 16333cd597fSDmitry Bezrukov 16433cd597fSDmitry Bezrukov return aqc111_write_cmd_nopm(dev, cmd, value, index, sizeof(tmp), &tmp); 16533cd597fSDmitry Bezrukov } 16633cd597fSDmitry Bezrukov 16733cd597fSDmitry Bezrukov static int aqc111_write32_cmd(struct usbnet *dev, u8 cmd, u16 value, 16833cd597fSDmitry Bezrukov u16 index, u32 *data) 16933cd597fSDmitry Bezrukov { 17033cd597fSDmitry Bezrukov u32 tmp = *data; 17133cd597fSDmitry Bezrukov 17233cd597fSDmitry Bezrukov cpu_to_le32s(&tmp); 17333cd597fSDmitry Bezrukov 17433cd597fSDmitry Bezrukov return aqc111_write_cmd(dev, cmd, value, index, sizeof(tmp), &tmp); 17533cd597fSDmitry Bezrukov } 17633cd597fSDmitry Bezrukov 17759b04eeaSDmitry Bezrukov static int aqc111_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, 17859b04eeaSDmitry Bezrukov u16 index, u16 size, void *data) 17959b04eeaSDmitry Bezrukov { 18059b04eeaSDmitry Bezrukov return usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | 18159b04eeaSDmitry Bezrukov USB_RECIP_DEVICE, value, index, data, 18259b04eeaSDmitry Bezrukov size); 18359b04eeaSDmitry Bezrukov } 18459b04eeaSDmitry Bezrukov 18559b04eeaSDmitry Bezrukov static int aqc111_write16_cmd_async(struct usbnet *dev, u8 cmd, u16 value, 18659b04eeaSDmitry Bezrukov u16 index, u16 *data) 18759b04eeaSDmitry Bezrukov { 18859b04eeaSDmitry Bezrukov u16 tmp = *data; 18959b04eeaSDmitry Bezrukov 19059b04eeaSDmitry Bezrukov cpu_to_le16s(&tmp); 19159b04eeaSDmitry Bezrukov 19259b04eeaSDmitry Bezrukov return aqc111_write_cmd_async(dev, cmd, value, index, 19359b04eeaSDmitry Bezrukov sizeof(tmp), &tmp); 19459b04eeaSDmitry Bezrukov } 19559b04eeaSDmitry Bezrukov 196027e6f78SDmitry Bezrukov static void aqc111_get_drvinfo(struct net_device *net, 197027e6f78SDmitry Bezrukov struct ethtool_drvinfo *info) 198027e6f78SDmitry Bezrukov { 199027e6f78SDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 200027e6f78SDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 201027e6f78SDmitry Bezrukov 202027e6f78SDmitry Bezrukov /* Inherit standard device info */ 203027e6f78SDmitry Bezrukov usbnet_get_drvinfo(net, info); 204027e6f78SDmitry Bezrukov strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver)); 205027e6f78SDmitry Bezrukov snprintf(info->fw_version, sizeof(info->fw_version), "%u.%u.%u", 206027e6f78SDmitry Bezrukov aqc111_data->fw_ver.major, 207027e6f78SDmitry Bezrukov aqc111_data->fw_ver.minor, 208027e6f78SDmitry Bezrukov aqc111_data->fw_ver.rev); 209027e6f78SDmitry Bezrukov info->eedump_len = 0x00; 210027e6f78SDmitry Bezrukov info->regdump_len = 0x00; 211027e6f78SDmitry Bezrukov } 212027e6f78SDmitry Bezrukov 213e58ba454SDmitry Bezrukov static void aqc111_get_wol(struct net_device *net, 214e58ba454SDmitry Bezrukov struct ethtool_wolinfo *wolinfo) 215e58ba454SDmitry Bezrukov { 216e58ba454SDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 217e58ba454SDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 218e58ba454SDmitry Bezrukov 219e58ba454SDmitry Bezrukov wolinfo->supported = WAKE_MAGIC; 220e58ba454SDmitry Bezrukov wolinfo->wolopts = 0; 221e58ba454SDmitry Bezrukov 222e58ba454SDmitry Bezrukov if (aqc111_data->wol_flags & AQ_WOL_FLAG_MP) 223e58ba454SDmitry Bezrukov wolinfo->wolopts |= WAKE_MAGIC; 224e58ba454SDmitry Bezrukov } 225e58ba454SDmitry Bezrukov 226e58ba454SDmitry Bezrukov static int aqc111_set_wol(struct net_device *net, 227e58ba454SDmitry Bezrukov struct ethtool_wolinfo *wolinfo) 228e58ba454SDmitry Bezrukov { 229e58ba454SDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 230e58ba454SDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 231e58ba454SDmitry Bezrukov 232e58ba454SDmitry Bezrukov if (wolinfo->wolopts & ~WAKE_MAGIC) 233e58ba454SDmitry Bezrukov return -EINVAL; 234e58ba454SDmitry Bezrukov 235e58ba454SDmitry Bezrukov aqc111_data->wol_flags = 0; 236e58ba454SDmitry Bezrukov if (wolinfo->wolopts & WAKE_MAGIC) 237e58ba454SDmitry Bezrukov aqc111_data->wol_flags |= AQ_WOL_FLAG_MP; 238e58ba454SDmitry Bezrukov 239e58ba454SDmitry Bezrukov return 0; 240e58ba454SDmitry Bezrukov } 241e58ba454SDmitry Bezrukov 242abbd8e7dSDmitry Bezrukov static void aqc111_speed_to_link_mode(u32 speed, 243abbd8e7dSDmitry Bezrukov struct ethtool_link_ksettings *elk) 244abbd8e7dSDmitry Bezrukov { 245abbd8e7dSDmitry Bezrukov switch (speed) { 246abbd8e7dSDmitry Bezrukov case SPEED_5000: 247abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_add_link_mode(elk, advertising, 248abbd8e7dSDmitry Bezrukov 5000baseT_Full); 249abbd8e7dSDmitry Bezrukov break; 250abbd8e7dSDmitry Bezrukov case SPEED_2500: 251abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_add_link_mode(elk, advertising, 252abbd8e7dSDmitry Bezrukov 2500baseT_Full); 253abbd8e7dSDmitry Bezrukov break; 254abbd8e7dSDmitry Bezrukov case SPEED_1000: 255abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_add_link_mode(elk, advertising, 256abbd8e7dSDmitry Bezrukov 1000baseT_Full); 257abbd8e7dSDmitry Bezrukov break; 258abbd8e7dSDmitry Bezrukov case SPEED_100: 259abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_add_link_mode(elk, advertising, 260abbd8e7dSDmitry Bezrukov 100baseT_Full); 261abbd8e7dSDmitry Bezrukov break; 262abbd8e7dSDmitry Bezrukov } 263abbd8e7dSDmitry Bezrukov } 264abbd8e7dSDmitry Bezrukov 265abbd8e7dSDmitry Bezrukov static int aqc111_get_link_ksettings(struct net_device *net, 266abbd8e7dSDmitry Bezrukov struct ethtool_link_ksettings *elk) 267abbd8e7dSDmitry Bezrukov { 268abbd8e7dSDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 269abbd8e7dSDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 270abbd8e7dSDmitry Bezrukov enum usb_device_speed usb_speed = dev->udev->speed; 271abbd8e7dSDmitry Bezrukov u32 speed = SPEED_UNKNOWN; 272abbd8e7dSDmitry Bezrukov 273abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_zero_link_mode(elk, supported); 274abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_add_link_mode(elk, supported, 275abbd8e7dSDmitry Bezrukov 100baseT_Full); 276abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_add_link_mode(elk, supported, 277abbd8e7dSDmitry Bezrukov 1000baseT_Full); 278abbd8e7dSDmitry Bezrukov if (usb_speed == USB_SPEED_SUPER) { 279abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_add_link_mode(elk, supported, 280abbd8e7dSDmitry Bezrukov 2500baseT_Full); 281abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_add_link_mode(elk, supported, 282abbd8e7dSDmitry Bezrukov 5000baseT_Full); 283abbd8e7dSDmitry Bezrukov } 284abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_add_link_mode(elk, supported, TP); 285abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_add_link_mode(elk, supported, Autoneg); 286abbd8e7dSDmitry Bezrukov 287abbd8e7dSDmitry Bezrukov elk->base.port = PORT_TP; 288abbd8e7dSDmitry Bezrukov elk->base.transceiver = XCVR_INTERNAL; 289abbd8e7dSDmitry Bezrukov 290abbd8e7dSDmitry Bezrukov elk->base.mdio_support = 0x00; /*Not supported*/ 291abbd8e7dSDmitry Bezrukov 292abbd8e7dSDmitry Bezrukov if (aqc111_data->autoneg) 293abbd8e7dSDmitry Bezrukov linkmode_copy(elk->link_modes.advertising, 294abbd8e7dSDmitry Bezrukov elk->link_modes.supported); 295abbd8e7dSDmitry Bezrukov else 296abbd8e7dSDmitry Bezrukov aqc111_speed_to_link_mode(aqc111_data->advertised_speed, elk); 297abbd8e7dSDmitry Bezrukov 298abbd8e7dSDmitry Bezrukov elk->base.autoneg = aqc111_data->autoneg; 299abbd8e7dSDmitry Bezrukov 300abbd8e7dSDmitry Bezrukov switch (aqc111_data->link_speed) { 301abbd8e7dSDmitry Bezrukov case AQ_INT_SPEED_5G: 302abbd8e7dSDmitry Bezrukov speed = SPEED_5000; 303abbd8e7dSDmitry Bezrukov break; 304abbd8e7dSDmitry Bezrukov case AQ_INT_SPEED_2_5G: 305abbd8e7dSDmitry Bezrukov speed = SPEED_2500; 306abbd8e7dSDmitry Bezrukov break; 307abbd8e7dSDmitry Bezrukov case AQ_INT_SPEED_1G: 308abbd8e7dSDmitry Bezrukov speed = SPEED_1000; 309abbd8e7dSDmitry Bezrukov break; 310abbd8e7dSDmitry Bezrukov case AQ_INT_SPEED_100M: 311abbd8e7dSDmitry Bezrukov speed = SPEED_100; 312abbd8e7dSDmitry Bezrukov break; 313abbd8e7dSDmitry Bezrukov } 314abbd8e7dSDmitry Bezrukov elk->base.duplex = DUPLEX_FULL; 315abbd8e7dSDmitry Bezrukov elk->base.speed = speed; 316abbd8e7dSDmitry Bezrukov 317abbd8e7dSDmitry Bezrukov return 0; 318abbd8e7dSDmitry Bezrukov } 319abbd8e7dSDmitry Bezrukov 3207b8b0654SDmitry Bezrukov static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed) 3217b8b0654SDmitry Bezrukov { 3227b8b0654SDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 3237b8b0654SDmitry Bezrukov 3247b8b0654SDmitry Bezrukov aqc111_data->phy_cfg &= ~AQ_ADV_MASK; 3257b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_PAUSE; 3267b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ASYM_PAUSE; 3277b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_DOWNSHIFT; 3287b8b0654SDmitry Bezrukov aqc111_data->phy_cfg &= ~AQ_DSH_RETRIES_MASK; 3297b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= (3 << AQ_DSH_RETRIES_SHIFT) & 3307b8b0654SDmitry Bezrukov AQ_DSH_RETRIES_MASK; 3317b8b0654SDmitry Bezrukov 3327b8b0654SDmitry Bezrukov if (autoneg == AUTONEG_ENABLE) { 3337b8b0654SDmitry Bezrukov switch (speed) { 3347b8b0654SDmitry Bezrukov case SPEED_5000: 3357b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_5G; 3367b8b0654SDmitry Bezrukov /* fall-through */ 3377b8b0654SDmitry Bezrukov case SPEED_2500: 3387b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_2G5; 3397b8b0654SDmitry Bezrukov /* fall-through */ 3407b8b0654SDmitry Bezrukov case SPEED_1000: 3417b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_1G; 3427b8b0654SDmitry Bezrukov /* fall-through */ 3437b8b0654SDmitry Bezrukov case SPEED_100: 3447b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_100M; 3457b8b0654SDmitry Bezrukov /* fall-through */ 3467b8b0654SDmitry Bezrukov } 3477b8b0654SDmitry Bezrukov } else { 3487b8b0654SDmitry Bezrukov switch (speed) { 3497b8b0654SDmitry Bezrukov case SPEED_5000: 3507b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_5G; 3517b8b0654SDmitry Bezrukov break; 3527b8b0654SDmitry Bezrukov case SPEED_2500: 3537b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_2G5; 3547b8b0654SDmitry Bezrukov break; 3557b8b0654SDmitry Bezrukov case SPEED_1000: 3567b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_1G; 3577b8b0654SDmitry Bezrukov break; 3587b8b0654SDmitry Bezrukov case SPEED_100: 3597b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_100M; 3607b8b0654SDmitry Bezrukov break; 3617b8b0654SDmitry Bezrukov } 3627b8b0654SDmitry Bezrukov } 3637b8b0654SDmitry Bezrukov 3647b8b0654SDmitry Bezrukov aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0, &aqc111_data->phy_cfg); 3657b8b0654SDmitry Bezrukov } 3667b8b0654SDmitry Bezrukov 367abbd8e7dSDmitry Bezrukov static int aqc111_set_link_ksettings(struct net_device *net, 368abbd8e7dSDmitry Bezrukov const struct ethtool_link_ksettings *elk) 369abbd8e7dSDmitry Bezrukov { 370abbd8e7dSDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 371abbd8e7dSDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 372abbd8e7dSDmitry Bezrukov enum usb_device_speed usb_speed = dev->udev->speed; 373abbd8e7dSDmitry Bezrukov u8 autoneg = elk->base.autoneg; 374abbd8e7dSDmitry Bezrukov u32 speed = elk->base.speed; 375abbd8e7dSDmitry Bezrukov 376abbd8e7dSDmitry Bezrukov if (autoneg == AUTONEG_ENABLE) { 377abbd8e7dSDmitry Bezrukov if (aqc111_data->autoneg != AUTONEG_ENABLE) { 378abbd8e7dSDmitry Bezrukov aqc111_data->autoneg = AUTONEG_ENABLE; 379abbd8e7dSDmitry Bezrukov aqc111_data->advertised_speed = 380abbd8e7dSDmitry Bezrukov (usb_speed == USB_SPEED_SUPER) ? 381abbd8e7dSDmitry Bezrukov SPEED_5000 : SPEED_1000; 382abbd8e7dSDmitry Bezrukov aqc111_set_phy_speed(dev, aqc111_data->autoneg, 383abbd8e7dSDmitry Bezrukov aqc111_data->advertised_speed); 384abbd8e7dSDmitry Bezrukov } 385abbd8e7dSDmitry Bezrukov } else { 386abbd8e7dSDmitry Bezrukov if (speed != SPEED_100 && 387abbd8e7dSDmitry Bezrukov speed != SPEED_1000 && 388abbd8e7dSDmitry Bezrukov speed != SPEED_2500 && 389abbd8e7dSDmitry Bezrukov speed != SPEED_5000 && 390abbd8e7dSDmitry Bezrukov speed != SPEED_UNKNOWN) 391abbd8e7dSDmitry Bezrukov return -EINVAL; 392abbd8e7dSDmitry Bezrukov 393abbd8e7dSDmitry Bezrukov if (elk->base.duplex != DUPLEX_FULL) 394abbd8e7dSDmitry Bezrukov return -EINVAL; 395abbd8e7dSDmitry Bezrukov 396abbd8e7dSDmitry Bezrukov if (usb_speed != USB_SPEED_SUPER && speed > SPEED_1000) 397abbd8e7dSDmitry Bezrukov return -EINVAL; 398abbd8e7dSDmitry Bezrukov 399abbd8e7dSDmitry Bezrukov aqc111_data->autoneg = AUTONEG_DISABLE; 400abbd8e7dSDmitry Bezrukov if (speed != SPEED_UNKNOWN) 401abbd8e7dSDmitry Bezrukov aqc111_data->advertised_speed = speed; 402abbd8e7dSDmitry Bezrukov 403abbd8e7dSDmitry Bezrukov aqc111_set_phy_speed(dev, aqc111_data->autoneg, 404abbd8e7dSDmitry Bezrukov aqc111_data->advertised_speed); 405abbd8e7dSDmitry Bezrukov } 406abbd8e7dSDmitry Bezrukov 407abbd8e7dSDmitry Bezrukov return 0; 408abbd8e7dSDmitry Bezrukov } 409abbd8e7dSDmitry Bezrukov 410027e6f78SDmitry Bezrukov static const struct ethtool_ops aqc111_ethtool_ops = { 411027e6f78SDmitry Bezrukov .get_drvinfo = aqc111_get_drvinfo, 412e58ba454SDmitry Bezrukov .get_wol = aqc111_get_wol, 413e58ba454SDmitry Bezrukov .set_wol = aqc111_set_wol, 414027e6f78SDmitry Bezrukov .get_msglevel = usbnet_get_msglevel, 415027e6f78SDmitry Bezrukov .set_msglevel = usbnet_set_msglevel, 416027e6f78SDmitry Bezrukov .get_link = ethtool_op_get_link, 417abbd8e7dSDmitry Bezrukov .get_link_ksettings = aqc111_get_link_ksettings, 418abbd8e7dSDmitry Bezrukov .set_link_ksettings = aqc111_set_link_ksettings 419027e6f78SDmitry Bezrukov }; 420027e6f78SDmitry Bezrukov 421a4017cc2SDmitry Bezrukov static int aqc111_change_mtu(struct net_device *net, int new_mtu) 422a4017cc2SDmitry Bezrukov { 423a4017cc2SDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 424a4017cc2SDmitry Bezrukov u16 reg16 = 0; 425a4017cc2SDmitry Bezrukov u8 buf[5]; 426a4017cc2SDmitry Bezrukov 427a4017cc2SDmitry Bezrukov net->mtu = new_mtu; 428a4017cc2SDmitry Bezrukov dev->hard_mtu = net->mtu + net->hard_header_len; 429a4017cc2SDmitry Bezrukov 430a4017cc2SDmitry Bezrukov aqc111_read16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 431a4017cc2SDmitry Bezrukov 2, ®16); 432a4017cc2SDmitry Bezrukov if (net->mtu > 1500) 433a4017cc2SDmitry Bezrukov reg16 |= SFR_MEDIUM_JUMBO_EN; 434a4017cc2SDmitry Bezrukov else 435a4017cc2SDmitry Bezrukov reg16 &= ~SFR_MEDIUM_JUMBO_EN; 436a4017cc2SDmitry Bezrukov 437a4017cc2SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 438a4017cc2SDmitry Bezrukov 2, ®16); 439a4017cc2SDmitry Bezrukov 440a4017cc2SDmitry Bezrukov if (dev->net->mtu > 12500 && dev->net->mtu <= 16334) { 441a4017cc2SDmitry Bezrukov memcpy(buf, &AQC111_BULKIN_SIZE[2], 5); 442a4017cc2SDmitry Bezrukov /* RX bulk configuration */ 443a4017cc2SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QCTRL, 444a4017cc2SDmitry Bezrukov 5, 5, buf); 445a4017cc2SDmitry Bezrukov } 446a4017cc2SDmitry Bezrukov 447a4017cc2SDmitry Bezrukov /* Set high low water level */ 448a4017cc2SDmitry Bezrukov if (dev->net->mtu <= 4500) 449a4017cc2SDmitry Bezrukov reg16 = 0x0810; 450a4017cc2SDmitry Bezrukov else if (dev->net->mtu <= 9500) 451a4017cc2SDmitry Bezrukov reg16 = 0x1020; 452a4017cc2SDmitry Bezrukov else if (dev->net->mtu <= 12500) 453a4017cc2SDmitry Bezrukov reg16 = 0x1420; 454a4017cc2SDmitry Bezrukov else if (dev->net->mtu <= 16334) 455a4017cc2SDmitry Bezrukov reg16 = 0x1A20; 456a4017cc2SDmitry Bezrukov 457a4017cc2SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_PAUSE_WATERLVL_LOW, 458a4017cc2SDmitry Bezrukov 2, ®16); 459a4017cc2SDmitry Bezrukov 460a4017cc2SDmitry Bezrukov return 0; 461a4017cc2SDmitry Bezrukov } 462a4017cc2SDmitry Bezrukov 463df2d59a2SDmitry Bezrukov static int aqc111_set_mac_addr(struct net_device *net, void *p) 464df2d59a2SDmitry Bezrukov { 465df2d59a2SDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 466df2d59a2SDmitry Bezrukov int ret = 0; 467df2d59a2SDmitry Bezrukov 468df2d59a2SDmitry Bezrukov ret = eth_mac_addr(net, p); 469df2d59a2SDmitry Bezrukov if (ret < 0) 470df2d59a2SDmitry Bezrukov return ret; 471df2d59a2SDmitry Bezrukov 472df2d59a2SDmitry Bezrukov /* Set the MAC address */ 473df2d59a2SDmitry Bezrukov return aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_NODE_ID, ETH_ALEN, 474df2d59a2SDmitry Bezrukov ETH_ALEN, net->dev_addr); 475df2d59a2SDmitry Bezrukov } 476df2d59a2SDmitry Bezrukov 4774189673aSDmitry Bezrukov static int aqc111_vlan_rx_kill_vid(struct net_device *net, 4784189673aSDmitry Bezrukov __be16 proto, u16 vid) 4794189673aSDmitry Bezrukov { 4804189673aSDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 4814189673aSDmitry Bezrukov u8 vlan_ctrl = 0; 4824189673aSDmitry Bezrukov u16 reg16 = 0; 4834189673aSDmitry Bezrukov u8 reg8 = 0; 4844189673aSDmitry Bezrukov 4854189673aSDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, ®8); 4864189673aSDmitry Bezrukov vlan_ctrl = reg8; 4874189673aSDmitry Bezrukov 4884189673aSDmitry Bezrukov /* Address */ 4894189673aSDmitry Bezrukov reg8 = (vid / 16); 4904189673aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_ADDRESS, 1, 1, ®8); 4914189673aSDmitry Bezrukov /* Data */ 4924189673aSDmitry Bezrukov reg8 = vlan_ctrl | SFR_VLAN_CONTROL_RD; 4934189673aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, ®8); 4944189673aSDmitry Bezrukov aqc111_read16_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, ®16); 4954189673aSDmitry Bezrukov reg16 &= ~(1 << (vid % 16)); 4964189673aSDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, ®16); 4974189673aSDmitry Bezrukov reg8 = vlan_ctrl | SFR_VLAN_CONTROL_WE; 4984189673aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, ®8); 4994189673aSDmitry Bezrukov 5004189673aSDmitry Bezrukov return 0; 5014189673aSDmitry Bezrukov } 5024189673aSDmitry Bezrukov 5034189673aSDmitry Bezrukov static int aqc111_vlan_rx_add_vid(struct net_device *net, __be16 proto, u16 vid) 5044189673aSDmitry Bezrukov { 5054189673aSDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 5064189673aSDmitry Bezrukov u8 vlan_ctrl = 0; 5074189673aSDmitry Bezrukov u16 reg16 = 0; 5084189673aSDmitry Bezrukov u8 reg8 = 0; 5094189673aSDmitry Bezrukov 5104189673aSDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, ®8); 5114189673aSDmitry Bezrukov vlan_ctrl = reg8; 5124189673aSDmitry Bezrukov 5134189673aSDmitry Bezrukov /* Address */ 5144189673aSDmitry Bezrukov reg8 = (vid / 16); 5154189673aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_ADDRESS, 1, 1, ®8); 5164189673aSDmitry Bezrukov /* Data */ 5174189673aSDmitry Bezrukov reg8 = vlan_ctrl | SFR_VLAN_CONTROL_RD; 5184189673aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, ®8); 5194189673aSDmitry Bezrukov aqc111_read16_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, ®16); 5204189673aSDmitry Bezrukov reg16 |= (1 << (vid % 16)); 5214189673aSDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, ®16); 5224189673aSDmitry Bezrukov reg8 = vlan_ctrl | SFR_VLAN_CONTROL_WE; 5234189673aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, ®8); 5244189673aSDmitry Bezrukov 5254189673aSDmitry Bezrukov return 0; 5264189673aSDmitry Bezrukov } 5274189673aSDmitry Bezrukov 52859b04eeaSDmitry Bezrukov static void aqc111_set_rx_mode(struct net_device *net) 52959b04eeaSDmitry Bezrukov { 53059b04eeaSDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 53159b04eeaSDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 53259b04eeaSDmitry Bezrukov int mc_count = 0; 53359b04eeaSDmitry Bezrukov 53459b04eeaSDmitry Bezrukov mc_count = netdev_mc_count(net); 53559b04eeaSDmitry Bezrukov 53659b04eeaSDmitry Bezrukov aqc111_data->rxctl &= ~(SFR_RX_CTL_PRO | SFR_RX_CTL_AMALL | 53759b04eeaSDmitry Bezrukov SFR_RX_CTL_AM); 53859b04eeaSDmitry Bezrukov 53959b04eeaSDmitry Bezrukov if (net->flags & IFF_PROMISC) { 54059b04eeaSDmitry Bezrukov aqc111_data->rxctl |= SFR_RX_CTL_PRO; 54159b04eeaSDmitry Bezrukov } else if ((net->flags & IFF_ALLMULTI) || mc_count > AQ_MAX_MCAST) { 54259b04eeaSDmitry Bezrukov aqc111_data->rxctl |= SFR_RX_CTL_AMALL; 54359b04eeaSDmitry Bezrukov } else if (!netdev_mc_empty(net)) { 54459b04eeaSDmitry Bezrukov u8 m_filter[AQ_MCAST_FILTER_SIZE] = { 0 }; 54559b04eeaSDmitry Bezrukov struct netdev_hw_addr *ha = NULL; 54659b04eeaSDmitry Bezrukov u32 crc_bits = 0; 54759b04eeaSDmitry Bezrukov 54859b04eeaSDmitry Bezrukov netdev_for_each_mc_addr(ha, net) { 54959b04eeaSDmitry Bezrukov crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; 55059b04eeaSDmitry Bezrukov m_filter[crc_bits >> 3] |= BIT(crc_bits & 7); 55159b04eeaSDmitry Bezrukov } 55259b04eeaSDmitry Bezrukov 55359b04eeaSDmitry Bezrukov aqc111_write_cmd_async(dev, AQ_ACCESS_MAC, 55459b04eeaSDmitry Bezrukov SFR_MULTI_FILTER_ARRY, 55559b04eeaSDmitry Bezrukov AQ_MCAST_FILTER_SIZE, 55659b04eeaSDmitry Bezrukov AQ_MCAST_FILTER_SIZE, m_filter); 55759b04eeaSDmitry Bezrukov 55859b04eeaSDmitry Bezrukov aqc111_data->rxctl |= SFR_RX_CTL_AM; 55959b04eeaSDmitry Bezrukov } 56059b04eeaSDmitry Bezrukov 56159b04eeaSDmitry Bezrukov aqc111_write16_cmd_async(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 56259b04eeaSDmitry Bezrukov 2, &aqc111_data->rxctl); 56359b04eeaSDmitry Bezrukov } 56459b04eeaSDmitry Bezrukov 5656649d2a6SDmitry Bezrukov static int aqc111_set_features(struct net_device *net, 5666649d2a6SDmitry Bezrukov netdev_features_t features) 5676649d2a6SDmitry Bezrukov { 5686649d2a6SDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 5696649d2a6SDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 5706649d2a6SDmitry Bezrukov netdev_features_t changed = net->features ^ features; 5714189673aSDmitry Bezrukov u16 reg16 = 0; 5726649d2a6SDmitry Bezrukov u8 reg8 = 0; 5736649d2a6SDmitry Bezrukov 5746649d2a6SDmitry Bezrukov if (changed & NETIF_F_IP_CSUM) { 5756649d2a6SDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, ®8); 5766649d2a6SDmitry Bezrukov reg8 ^= SFR_TXCOE_TCP | SFR_TXCOE_UDP; 5776649d2a6SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 5786649d2a6SDmitry Bezrukov 1, 1, ®8); 5796649d2a6SDmitry Bezrukov } 5806649d2a6SDmitry Bezrukov 5816649d2a6SDmitry Bezrukov if (changed & NETIF_F_IPV6_CSUM) { 5826649d2a6SDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, ®8); 5836649d2a6SDmitry Bezrukov reg8 ^= SFR_TXCOE_TCPV6 | SFR_TXCOE_UDPV6; 5846649d2a6SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 5856649d2a6SDmitry Bezrukov 1, 1, ®8); 5866649d2a6SDmitry Bezrukov } 5876649d2a6SDmitry Bezrukov 5886649d2a6SDmitry Bezrukov if (changed & NETIF_F_RXCSUM) { 5896649d2a6SDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL, 1, 1, ®8); 5906649d2a6SDmitry Bezrukov if (features & NETIF_F_RXCSUM) { 5916649d2a6SDmitry Bezrukov aqc111_data->rx_checksum = 1; 5926649d2a6SDmitry Bezrukov reg8 &= ~(SFR_RXCOE_IP | SFR_RXCOE_TCP | SFR_RXCOE_UDP | 5936649d2a6SDmitry Bezrukov SFR_RXCOE_TCPV6 | SFR_RXCOE_UDPV6); 5946649d2a6SDmitry Bezrukov } else { 5956649d2a6SDmitry Bezrukov aqc111_data->rx_checksum = 0; 5966649d2a6SDmitry Bezrukov reg8 |= SFR_RXCOE_IP | SFR_RXCOE_TCP | SFR_RXCOE_UDP | 5976649d2a6SDmitry Bezrukov SFR_RXCOE_TCPV6 | SFR_RXCOE_UDPV6; 5986649d2a6SDmitry Bezrukov } 5996649d2a6SDmitry Bezrukov 6006649d2a6SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL, 6016649d2a6SDmitry Bezrukov 1, 1, ®8); 6026649d2a6SDmitry Bezrukov } 6034189673aSDmitry Bezrukov if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) { 6044189673aSDmitry Bezrukov if (features & NETIF_F_HW_VLAN_CTAG_FILTER) { 6054189673aSDmitry Bezrukov u16 i = 0; 6064189673aSDmitry Bezrukov 6074189673aSDmitry Bezrukov for (i = 0; i < 256; i++) { 6084189673aSDmitry Bezrukov /* Address */ 6094189673aSDmitry Bezrukov reg8 = i; 6104189673aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, 6114189673aSDmitry Bezrukov SFR_VLAN_ID_ADDRESS, 6124189673aSDmitry Bezrukov 1, 1, ®8); 6134189673aSDmitry Bezrukov /* Data */ 6144189673aSDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, 6154189673aSDmitry Bezrukov SFR_VLAN_ID_DATA0, 6164189673aSDmitry Bezrukov 2, ®16); 6174189673aSDmitry Bezrukov reg8 = SFR_VLAN_CONTROL_WE; 6184189673aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, 6194189673aSDmitry Bezrukov SFR_VLAN_ID_CONTROL, 6204189673aSDmitry Bezrukov 1, 1, ®8); 6214189673aSDmitry Bezrukov } 6224189673aSDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 6234189673aSDmitry Bezrukov 1, 1, ®8); 6244189673aSDmitry Bezrukov reg8 |= SFR_VLAN_CONTROL_VFE; 6254189673aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, 6264189673aSDmitry Bezrukov SFR_VLAN_ID_CONTROL, 1, 1, ®8); 6274189673aSDmitry Bezrukov } else { 6284189673aSDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 6294189673aSDmitry Bezrukov 1, 1, ®8); 6304189673aSDmitry Bezrukov reg8 &= ~SFR_VLAN_CONTROL_VFE; 6314189673aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, 6324189673aSDmitry Bezrukov SFR_VLAN_ID_CONTROL, 1, 1, ®8); 6334189673aSDmitry Bezrukov } 6344189673aSDmitry Bezrukov } 6354189673aSDmitry Bezrukov 6366649d2a6SDmitry Bezrukov return 0; 6376649d2a6SDmitry Bezrukov } 6386649d2a6SDmitry Bezrukov 6397cea2d40SDmitry Bezrukov static const struct net_device_ops aqc111_netdev_ops = { 6407cea2d40SDmitry Bezrukov .ndo_open = usbnet_open, 6417cea2d40SDmitry Bezrukov .ndo_stop = usbnet_stop, 6424a3576d2SDmitry Bezrukov .ndo_start_xmit = usbnet_start_xmit, 6434a3576d2SDmitry Bezrukov .ndo_tx_timeout = usbnet_tx_timeout, 6444a3576d2SDmitry Bezrukov .ndo_get_stats64 = usbnet_get_stats64, 645a4017cc2SDmitry Bezrukov .ndo_change_mtu = aqc111_change_mtu, 646df2d59a2SDmitry Bezrukov .ndo_set_mac_address = aqc111_set_mac_addr, 647df2d59a2SDmitry Bezrukov .ndo_validate_addr = eth_validate_addr, 6484189673aSDmitry Bezrukov .ndo_vlan_rx_add_vid = aqc111_vlan_rx_add_vid, 6494189673aSDmitry Bezrukov .ndo_vlan_rx_kill_vid = aqc111_vlan_rx_kill_vid, 65059b04eeaSDmitry Bezrukov .ndo_set_rx_mode = aqc111_set_rx_mode, 6516649d2a6SDmitry Bezrukov .ndo_set_features = aqc111_set_features, 6527cea2d40SDmitry Bezrukov }; 6537cea2d40SDmitry Bezrukov 654df2d59a2SDmitry Bezrukov static int aqc111_read_perm_mac(struct usbnet *dev) 655df2d59a2SDmitry Bezrukov { 656df2d59a2SDmitry Bezrukov u8 buf[ETH_ALEN]; 657df2d59a2SDmitry Bezrukov int ret; 658df2d59a2SDmitry Bezrukov 659df2d59a2SDmitry Bezrukov ret = aqc111_read_cmd(dev, AQ_FLASH_PARAMETERS, 0, 0, ETH_ALEN, buf); 660df2d59a2SDmitry Bezrukov if (ret < 0) 661df2d59a2SDmitry Bezrukov goto out; 662df2d59a2SDmitry Bezrukov 663df2d59a2SDmitry Bezrukov ether_addr_copy(dev->net->perm_addr, buf); 664df2d59a2SDmitry Bezrukov 665df2d59a2SDmitry Bezrukov return 0; 666df2d59a2SDmitry Bezrukov out: 667df2d59a2SDmitry Bezrukov return ret; 668df2d59a2SDmitry Bezrukov } 669df2d59a2SDmitry Bezrukov 67033cd597fSDmitry Bezrukov static void aqc111_read_fw_version(struct usbnet *dev, 67133cd597fSDmitry Bezrukov struct aqc111_data *aqc111_data) 67233cd597fSDmitry Bezrukov { 67333cd597fSDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MAJOR, 67433cd597fSDmitry Bezrukov 1, 1, &aqc111_data->fw_ver.major); 67533cd597fSDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MINOR, 67633cd597fSDmitry Bezrukov 1, 1, &aqc111_data->fw_ver.minor); 67733cd597fSDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_REV, 67833cd597fSDmitry Bezrukov 1, 1, &aqc111_data->fw_ver.rev); 67933cd597fSDmitry Bezrukov 68033cd597fSDmitry Bezrukov if (aqc111_data->fw_ver.major & 0x80) 68133cd597fSDmitry Bezrukov aqc111_data->fw_ver.major &= ~0x80; 68233cd597fSDmitry Bezrukov } 68333cd597fSDmitry Bezrukov 6847cea2d40SDmitry Bezrukov static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf) 6857cea2d40SDmitry Bezrukov { 6867cea2d40SDmitry Bezrukov struct usb_device *udev = interface_to_usbdev(intf); 6877b8b0654SDmitry Bezrukov enum usb_device_speed usb_speed = udev->speed; 68833cd597fSDmitry Bezrukov struct aqc111_data *aqc111_data; 6897cea2d40SDmitry Bezrukov int ret; 6907cea2d40SDmitry Bezrukov 6917cea2d40SDmitry Bezrukov /* Check if vendor configuration */ 6927cea2d40SDmitry Bezrukov if (udev->actconfig->desc.bConfigurationValue != 1) { 6937cea2d40SDmitry Bezrukov usb_driver_set_configuration(udev, 1); 6947cea2d40SDmitry Bezrukov return -ENODEV; 6957cea2d40SDmitry Bezrukov } 6967cea2d40SDmitry Bezrukov 6977cea2d40SDmitry Bezrukov usb_reset_configuration(dev->udev); 6987cea2d40SDmitry Bezrukov 6997cea2d40SDmitry Bezrukov ret = usbnet_get_endpoints(dev, intf); 7007cea2d40SDmitry Bezrukov if (ret < 0) { 7017cea2d40SDmitry Bezrukov netdev_dbg(dev->net, "usbnet_get_endpoints failed"); 7027cea2d40SDmitry Bezrukov return ret; 7037cea2d40SDmitry Bezrukov } 7047cea2d40SDmitry Bezrukov 70533cd597fSDmitry Bezrukov aqc111_data = kzalloc(sizeof(*aqc111_data), GFP_KERNEL); 70633cd597fSDmitry Bezrukov if (!aqc111_data) 70733cd597fSDmitry Bezrukov return -ENOMEM; 70833cd597fSDmitry Bezrukov 70933cd597fSDmitry Bezrukov /* store aqc111_data pointer in device data field */ 71033cd597fSDmitry Bezrukov dev->driver_priv = aqc111_data; 71133cd597fSDmitry Bezrukov 712df2d59a2SDmitry Bezrukov /* Init the MAC address */ 713df2d59a2SDmitry Bezrukov ret = aqc111_read_perm_mac(dev); 714df2d59a2SDmitry Bezrukov if (ret) 715df2d59a2SDmitry Bezrukov goto out; 716df2d59a2SDmitry Bezrukov 717df2d59a2SDmitry Bezrukov ether_addr_copy(dev->net->dev_addr, dev->net->perm_addr); 7184a3576d2SDmitry Bezrukov 719361459cdSDmitry Bezrukov /* Set Rx urb size */ 720361459cdSDmitry Bezrukov dev->rx_urb_size = URB_SIZE; 721361459cdSDmitry Bezrukov 7224a3576d2SDmitry Bezrukov /* Set TX needed headroom & tailroom */ 7234a3576d2SDmitry Bezrukov dev->net->needed_headroom += sizeof(u64); 7244a3576d2SDmitry Bezrukov dev->net->needed_tailroom += sizeof(u64); 7254a3576d2SDmitry Bezrukov 726a4017cc2SDmitry Bezrukov dev->net->max_mtu = 16334; 727a4017cc2SDmitry Bezrukov 7287cea2d40SDmitry Bezrukov dev->net->netdev_ops = &aqc111_netdev_ops; 729027e6f78SDmitry Bezrukov dev->net->ethtool_ops = &aqc111_ethtool_ops; 7307cea2d40SDmitry Bezrukov 7314a3576d2SDmitry Bezrukov if (usb_device_no_sg_constraint(dev->udev)) 7324a3576d2SDmitry Bezrukov dev->can_dma_sg = 1; 7334a3576d2SDmitry Bezrukov 7344a3576d2SDmitry Bezrukov dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE; 7354a3576d2SDmitry Bezrukov dev->net->features |= AQ_SUPPORT_FEATURE; 7367afa6c98SDmitry Bezrukov dev->net->vlan_features |= AQ_SUPPORT_VLAN_FEATURE; 7374a3576d2SDmitry Bezrukov 738de074e7aSDmitry Bezrukov netif_set_gso_max_size(dev->net, 65535); 739de074e7aSDmitry Bezrukov 74033cd597fSDmitry Bezrukov aqc111_read_fw_version(dev, aqc111_data); 7417b8b0654SDmitry Bezrukov aqc111_data->autoneg = AUTONEG_ENABLE; 7427b8b0654SDmitry Bezrukov aqc111_data->advertised_speed = (usb_speed == USB_SPEED_SUPER) ? 7437b8b0654SDmitry Bezrukov SPEED_5000 : SPEED_1000; 74433cd597fSDmitry Bezrukov 7457cea2d40SDmitry Bezrukov return 0; 746df2d59a2SDmitry Bezrukov 747df2d59a2SDmitry Bezrukov out: 748df2d59a2SDmitry Bezrukov kfree(aqc111_data); 749df2d59a2SDmitry Bezrukov return ret; 7507cea2d40SDmitry Bezrukov } 7517cea2d40SDmitry Bezrukov 7527cea2d40SDmitry Bezrukov static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf) 7537cea2d40SDmitry Bezrukov { 75433cd597fSDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 755f3aa095aSDmitry Bezrukov u16 reg16; 756f3aa095aSDmitry Bezrukov 757f3aa095aSDmitry Bezrukov /* Force bz */ 758f3aa095aSDmitry Bezrukov reg16 = SFR_PHYPWR_RSTCTL_BZ; 759f3aa095aSDmitry Bezrukov aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL, 760f3aa095aSDmitry Bezrukov 2, ®16); 761f3aa095aSDmitry Bezrukov reg16 = 0; 762f3aa095aSDmitry Bezrukov aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL, 763f3aa095aSDmitry Bezrukov 2, ®16); 76433cd597fSDmitry Bezrukov 76533cd597fSDmitry Bezrukov /* Power down ethernet PHY */ 7667b8b0654SDmitry Bezrukov aqc111_data->phy_cfg &= ~AQ_ADV_MASK; 76733cd597fSDmitry Bezrukov aqc111_data->phy_cfg |= AQ_LOW_POWER; 76833cd597fSDmitry Bezrukov aqc111_data->phy_cfg &= ~AQ_PHY_POWER_EN; 76933cd597fSDmitry Bezrukov aqc111_write32_cmd_nopm(dev, AQ_PHY_OPS, 0, 0, 77033cd597fSDmitry Bezrukov &aqc111_data->phy_cfg); 77133cd597fSDmitry Bezrukov 77233cd597fSDmitry Bezrukov kfree(aqc111_data); 773f3aa095aSDmitry Bezrukov } 774f3aa095aSDmitry Bezrukov 7757b8b0654SDmitry Bezrukov static void aqc111_status(struct usbnet *dev, struct urb *urb) 7767b8b0654SDmitry Bezrukov { 7777b8b0654SDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 7787b8b0654SDmitry Bezrukov u64 *event_data = NULL; 7797b8b0654SDmitry Bezrukov int link = 0; 7807b8b0654SDmitry Bezrukov 7817b8b0654SDmitry Bezrukov if (urb->actual_length < sizeof(*event_data)) 7827b8b0654SDmitry Bezrukov return; 7837b8b0654SDmitry Bezrukov 7847b8b0654SDmitry Bezrukov event_data = urb->transfer_buffer; 7857b8b0654SDmitry Bezrukov le64_to_cpus(event_data); 7867b8b0654SDmitry Bezrukov 7877b8b0654SDmitry Bezrukov if (*event_data & AQ_LS_MASK) 7887b8b0654SDmitry Bezrukov link = 1; 7897b8b0654SDmitry Bezrukov else 7907b8b0654SDmitry Bezrukov link = 0; 7917b8b0654SDmitry Bezrukov 7927b8b0654SDmitry Bezrukov aqc111_data->link_speed = (*event_data & AQ_SPEED_MASK) >> 7937b8b0654SDmitry Bezrukov AQ_SPEED_SHIFT; 7947b8b0654SDmitry Bezrukov aqc111_data->link = link; 7957b8b0654SDmitry Bezrukov 7967b8b0654SDmitry Bezrukov if (netif_carrier_ok(dev->net) != link) 7977b8b0654SDmitry Bezrukov usbnet_defer_kevent(dev, EVENT_LINK_RESET); 7987b8b0654SDmitry Bezrukov } 7997b8b0654SDmitry Bezrukov 8007b8b0654SDmitry Bezrukov static void aqc111_configure_rx(struct usbnet *dev, 8017b8b0654SDmitry Bezrukov struct aqc111_data *aqc111_data) 8027b8b0654SDmitry Bezrukov { 8037b8b0654SDmitry Bezrukov enum usb_device_speed usb_speed = dev->udev->speed; 8047b8b0654SDmitry Bezrukov u16 link_speed = 0, usb_host = 0; 8057b8b0654SDmitry Bezrukov u8 buf[5] = { 0 }; 8067b8b0654SDmitry Bezrukov u8 queue_num = 0; 8077b8b0654SDmitry Bezrukov u16 reg16 = 0; 8087b8b0654SDmitry Bezrukov u8 reg8 = 0; 8097b8b0654SDmitry Bezrukov 8107b8b0654SDmitry Bezrukov buf[0] = 0x00; 8117b8b0654SDmitry Bezrukov buf[1] = 0xF8; 8127b8b0654SDmitry Bezrukov buf[2] = 0x07; 8137b8b0654SDmitry Bezrukov switch (aqc111_data->link_speed) { 8147b8b0654SDmitry Bezrukov case AQ_INT_SPEED_5G: 8157b8b0654SDmitry Bezrukov link_speed = 5000; 8167b8b0654SDmitry Bezrukov reg8 = 0x05; 8177b8b0654SDmitry Bezrukov reg16 = 0x001F; 8187b8b0654SDmitry Bezrukov break; 8197b8b0654SDmitry Bezrukov case AQ_INT_SPEED_2_5G: 8207b8b0654SDmitry Bezrukov link_speed = 2500; 8217b8b0654SDmitry Bezrukov reg16 = 0x003F; 8227b8b0654SDmitry Bezrukov break; 8237b8b0654SDmitry Bezrukov case AQ_INT_SPEED_1G: 8247b8b0654SDmitry Bezrukov link_speed = 1000; 8257b8b0654SDmitry Bezrukov reg16 = 0x009F; 8267b8b0654SDmitry Bezrukov break; 8277b8b0654SDmitry Bezrukov case AQ_INT_SPEED_100M: 8287b8b0654SDmitry Bezrukov link_speed = 100; 8297b8b0654SDmitry Bezrukov queue_num = 1; 8307b8b0654SDmitry Bezrukov reg16 = 0x063F; 8317b8b0654SDmitry Bezrukov buf[1] = 0xFB; 8327b8b0654SDmitry Bezrukov buf[2] = 0x4; 8337b8b0654SDmitry Bezrukov break; 8347b8b0654SDmitry Bezrukov } 8357b8b0654SDmitry Bezrukov 8367b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_INTER_PACKET_GAP_0, 8377b8b0654SDmitry Bezrukov 1, 1, ®8); 8387b8b0654SDmitry Bezrukov 8397b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TX_PAUSE_RESEND_T, 3, 3, buf); 8407b8b0654SDmitry Bezrukov 8417b8b0654SDmitry Bezrukov switch (usb_speed) { 8427b8b0654SDmitry Bezrukov case USB_SPEED_SUPER: 8437b8b0654SDmitry Bezrukov usb_host = 3; 8447b8b0654SDmitry Bezrukov break; 8457b8b0654SDmitry Bezrukov case USB_SPEED_HIGH: 8467b8b0654SDmitry Bezrukov usb_host = 2; 8477b8b0654SDmitry Bezrukov break; 8487b8b0654SDmitry Bezrukov case USB_SPEED_FULL: 8497b8b0654SDmitry Bezrukov case USB_SPEED_LOW: 8507b8b0654SDmitry Bezrukov usb_host = 1; 8517b8b0654SDmitry Bezrukov queue_num = 0; 8527b8b0654SDmitry Bezrukov break; 8537b8b0654SDmitry Bezrukov default: 8547b8b0654SDmitry Bezrukov usb_host = 0; 8557b8b0654SDmitry Bezrukov break; 8567b8b0654SDmitry Bezrukov } 8577b8b0654SDmitry Bezrukov 858a4017cc2SDmitry Bezrukov if (dev->net->mtu > 12500 && dev->net->mtu <= 16334) 859a4017cc2SDmitry Bezrukov queue_num = 2; /* For Jumbo packet 16KB */ 860a4017cc2SDmitry Bezrukov 8617b8b0654SDmitry Bezrukov memcpy(buf, &AQC111_BULKIN_SIZE[queue_num], 5); 8627b8b0654SDmitry Bezrukov /* RX bulk configuration */ 8637b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QCTRL, 5, 5, buf); 8647b8b0654SDmitry Bezrukov 8657b8b0654SDmitry Bezrukov /* Set high low water level */ 866a4017cc2SDmitry Bezrukov if (dev->net->mtu <= 4500) 8677b8b0654SDmitry Bezrukov reg16 = 0x0810; 868a4017cc2SDmitry Bezrukov else if (dev->net->mtu <= 9500) 869a4017cc2SDmitry Bezrukov reg16 = 0x1020; 870a4017cc2SDmitry Bezrukov else if (dev->net->mtu <= 12500) 871a4017cc2SDmitry Bezrukov reg16 = 0x1420; 872a4017cc2SDmitry Bezrukov else if (dev->net->mtu <= 16334) 873a4017cc2SDmitry Bezrukov reg16 = 0x1A20; 8747b8b0654SDmitry Bezrukov 8757b8b0654SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_PAUSE_WATERLVL_LOW, 8767b8b0654SDmitry Bezrukov 2, ®16); 8777b8b0654SDmitry Bezrukov netdev_info(dev->net, "Link Speed %d, USB %d", link_speed, usb_host); 8787b8b0654SDmitry Bezrukov } 8797b8b0654SDmitry Bezrukov 88002031466SDmitry Bezrukov static void aqc111_configure_csum_offload(struct usbnet *dev) 88102031466SDmitry Bezrukov { 88202031466SDmitry Bezrukov u8 reg8 = 0; 88302031466SDmitry Bezrukov 88402031466SDmitry Bezrukov if (dev->net->features & NETIF_F_RXCSUM) { 88502031466SDmitry Bezrukov reg8 |= SFR_RXCOE_IP | SFR_RXCOE_TCP | SFR_RXCOE_UDP | 88602031466SDmitry Bezrukov SFR_RXCOE_TCPV6 | SFR_RXCOE_UDPV6; 88702031466SDmitry Bezrukov } 88802031466SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL, 1, 1, ®8); 88902031466SDmitry Bezrukov 89002031466SDmitry Bezrukov reg8 = 0; 89102031466SDmitry Bezrukov if (dev->net->features & NETIF_F_IP_CSUM) 89202031466SDmitry Bezrukov reg8 |= SFR_TXCOE_IP | SFR_TXCOE_TCP | SFR_TXCOE_UDP; 89302031466SDmitry Bezrukov 89402031466SDmitry Bezrukov if (dev->net->features & NETIF_F_IPV6_CSUM) 89502031466SDmitry Bezrukov reg8 |= SFR_TXCOE_TCPV6 | SFR_TXCOE_UDPV6; 89602031466SDmitry Bezrukov 89702031466SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, ®8); 89802031466SDmitry Bezrukov } 89902031466SDmitry Bezrukov 9007b8b0654SDmitry Bezrukov static int aqc111_link_reset(struct usbnet *dev) 9017b8b0654SDmitry Bezrukov { 9027b8b0654SDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 9037b8b0654SDmitry Bezrukov u16 reg16 = 0; 9047b8b0654SDmitry Bezrukov u8 reg8 = 0; 9057b8b0654SDmitry Bezrukov 9067b8b0654SDmitry Bezrukov if (aqc111_data->link == 1) { /* Link up */ 9077b8b0654SDmitry Bezrukov aqc111_configure_rx(dev, aqc111_data); 9087b8b0654SDmitry Bezrukov 9097b8b0654SDmitry Bezrukov /* Vlan Tag Filter */ 9107b8b0654SDmitry Bezrukov reg8 = SFR_VLAN_CONTROL_VSO; 9114189673aSDmitry Bezrukov if (dev->net->features & NETIF_F_HW_VLAN_CTAG_FILTER) 9124189673aSDmitry Bezrukov reg8 |= SFR_VLAN_CONTROL_VFE; 9137b8b0654SDmitry Bezrukov 9147b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 9157b8b0654SDmitry Bezrukov 1, 1, ®8); 9167b8b0654SDmitry Bezrukov 9177b8b0654SDmitry Bezrukov reg8 = 0x0; 9187b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BMRX_DMA_CONTROL, 9197b8b0654SDmitry Bezrukov 1, 1, ®8); 9207b8b0654SDmitry Bezrukov 9217b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BMTX_DMA_CONTROL, 9227b8b0654SDmitry Bezrukov 1, 1, ®8); 9237b8b0654SDmitry Bezrukov 9247b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_ARC_CTRL, 1, 1, ®8); 9257b8b0654SDmitry Bezrukov 9267b8b0654SDmitry Bezrukov reg16 = SFR_RX_CTL_IPE | SFR_RX_CTL_AB; 92759b04eeaSDmitry Bezrukov aqc111_data->rxctl = reg16; 9287b8b0654SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, ®16); 9297b8b0654SDmitry Bezrukov 9307b8b0654SDmitry Bezrukov reg8 = SFR_RX_PATH_READY; 9317b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH, 9327b8b0654SDmitry Bezrukov 1, 1, ®8); 9337b8b0654SDmitry Bezrukov 9347b8b0654SDmitry Bezrukov reg8 = SFR_BULK_OUT_EFF_EN; 9357b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL, 9367b8b0654SDmitry Bezrukov 1, 1, ®8); 9377b8b0654SDmitry Bezrukov 9387b8b0654SDmitry Bezrukov reg16 = 0; 9397b8b0654SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 9407b8b0654SDmitry Bezrukov 2, ®16); 9417b8b0654SDmitry Bezrukov 9427b8b0654SDmitry Bezrukov reg16 = SFR_MEDIUM_XGMIIMODE | SFR_MEDIUM_FULL_DUPLEX; 9437b8b0654SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 9447b8b0654SDmitry Bezrukov 2, ®16); 9457b8b0654SDmitry Bezrukov 94602031466SDmitry Bezrukov aqc111_configure_csum_offload(dev); 94702031466SDmitry Bezrukov 94859b04eeaSDmitry Bezrukov aqc111_set_rx_mode(dev->net); 94959b04eeaSDmitry Bezrukov 9507b8b0654SDmitry Bezrukov aqc111_read16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 9517b8b0654SDmitry Bezrukov 2, ®16); 9527b8b0654SDmitry Bezrukov 953a4017cc2SDmitry Bezrukov if (dev->net->mtu > 1500) 954a4017cc2SDmitry Bezrukov reg16 |= SFR_MEDIUM_JUMBO_EN; 955a4017cc2SDmitry Bezrukov 9567b8b0654SDmitry Bezrukov reg16 |= SFR_MEDIUM_RECEIVE_EN | SFR_MEDIUM_RXFLOW_CTRLEN | 9577b8b0654SDmitry Bezrukov SFR_MEDIUM_TXFLOW_CTRLEN; 9587b8b0654SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 9597b8b0654SDmitry Bezrukov 2, ®16); 9607b8b0654SDmitry Bezrukov 96159b04eeaSDmitry Bezrukov aqc111_data->rxctl |= SFR_RX_CTL_START; 96259b04eeaSDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 96359b04eeaSDmitry Bezrukov 2, &aqc111_data->rxctl); 9647b8b0654SDmitry Bezrukov 9657b8b0654SDmitry Bezrukov netif_carrier_on(dev->net); 9667b8b0654SDmitry Bezrukov } else { 9677b8b0654SDmitry Bezrukov aqc111_read16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 9687b8b0654SDmitry Bezrukov 2, ®16); 9697b8b0654SDmitry Bezrukov reg16 &= ~SFR_MEDIUM_RECEIVE_EN; 9707b8b0654SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 9717b8b0654SDmitry Bezrukov 2, ®16); 9727b8b0654SDmitry Bezrukov 97359b04eeaSDmitry Bezrukov aqc111_data->rxctl &= ~SFR_RX_CTL_START; 97459b04eeaSDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 97559b04eeaSDmitry Bezrukov 2, &aqc111_data->rxctl); 9767b8b0654SDmitry Bezrukov 9777b8b0654SDmitry Bezrukov reg8 = SFR_BULK_OUT_FLUSH_EN | SFR_BULK_OUT_EFF_EN; 9787b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL, 9797b8b0654SDmitry Bezrukov 1, 1, ®8); 9807b8b0654SDmitry Bezrukov reg8 = SFR_BULK_OUT_EFF_EN; 9817b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL, 9827b8b0654SDmitry Bezrukov 1, 1, ®8); 9837b8b0654SDmitry Bezrukov 9847b8b0654SDmitry Bezrukov netif_carrier_off(dev->net); 9857b8b0654SDmitry Bezrukov } 9867b8b0654SDmitry Bezrukov return 0; 9877b8b0654SDmitry Bezrukov } 9887b8b0654SDmitry Bezrukov 989f3aa095aSDmitry Bezrukov static int aqc111_reset(struct usbnet *dev) 990f3aa095aSDmitry Bezrukov { 99133cd597fSDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 992f3aa095aSDmitry Bezrukov u8 reg8 = 0; 993f3aa095aSDmitry Bezrukov 994361459cdSDmitry Bezrukov dev->rx_urb_size = URB_SIZE; 995361459cdSDmitry Bezrukov 9964a3576d2SDmitry Bezrukov if (usb_device_no_sg_constraint(dev->udev)) 9974a3576d2SDmitry Bezrukov dev->can_dma_sg = 1; 9984a3576d2SDmitry Bezrukov 9994a3576d2SDmitry Bezrukov dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE; 10004a3576d2SDmitry Bezrukov dev->net->features |= AQ_SUPPORT_FEATURE; 10017afa6c98SDmitry Bezrukov dev->net->vlan_features |= AQ_SUPPORT_VLAN_FEATURE; 10024a3576d2SDmitry Bezrukov 100333cd597fSDmitry Bezrukov /* Power up ethernet PHY */ 100433cd597fSDmitry Bezrukov aqc111_data->phy_cfg = AQ_PHY_POWER_EN; 100533cd597fSDmitry Bezrukov aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0, 100633cd597fSDmitry Bezrukov &aqc111_data->phy_cfg); 100733cd597fSDmitry Bezrukov 1008df2d59a2SDmitry Bezrukov /* Set the MAC address */ 1009df2d59a2SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_NODE_ID, ETH_ALEN, 1010df2d59a2SDmitry Bezrukov ETH_ALEN, dev->net->dev_addr); 1011df2d59a2SDmitry Bezrukov 1012f3aa095aSDmitry Bezrukov reg8 = 0xFF; 1013f3aa095aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK, 1, 1, ®8); 1014f3aa095aSDmitry Bezrukov 1015f3aa095aSDmitry Bezrukov reg8 = 0x0; 1016f3aa095aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_SWP_CTRL, 1, 1, ®8); 1017f3aa095aSDmitry Bezrukov 1018f3aa095aSDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MONITOR_MODE, 1, 1, ®8); 1019f3aa095aSDmitry Bezrukov reg8 &= ~(SFR_MONITOR_MODE_EPHYRW | SFR_MONITOR_MODE_RWLC | 1020f3aa095aSDmitry Bezrukov SFR_MONITOR_MODE_RWMP | SFR_MONITOR_MODE_RWWF | 1021f3aa095aSDmitry Bezrukov SFR_MONITOR_MODE_RW_FLAG); 1022f3aa095aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MONITOR_MODE, 1, 1, ®8); 1023f3aa095aSDmitry Bezrukov 10247b8b0654SDmitry Bezrukov netif_carrier_off(dev->net); 10257b8b0654SDmitry Bezrukov 10267b8b0654SDmitry Bezrukov /* Phy advertise */ 10277b8b0654SDmitry Bezrukov aqc111_set_phy_speed(dev, aqc111_data->autoneg, 10287b8b0654SDmitry Bezrukov aqc111_data->advertised_speed); 10297b8b0654SDmitry Bezrukov 1030f3aa095aSDmitry Bezrukov return 0; 1031f3aa095aSDmitry Bezrukov } 1032f3aa095aSDmitry Bezrukov 1033f3aa095aSDmitry Bezrukov static int aqc111_stop(struct usbnet *dev) 1034f3aa095aSDmitry Bezrukov { 103533cd597fSDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 1036f3aa095aSDmitry Bezrukov u16 reg16 = 0; 1037f3aa095aSDmitry Bezrukov 1038f3aa095aSDmitry Bezrukov aqc111_read16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 1039f3aa095aSDmitry Bezrukov 2, ®16); 1040f3aa095aSDmitry Bezrukov reg16 &= ~SFR_MEDIUM_RECEIVE_EN; 1041f3aa095aSDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 1042f3aa095aSDmitry Bezrukov 2, ®16); 1043f3aa095aSDmitry Bezrukov reg16 = 0; 1044f3aa095aSDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, ®16); 1045f3aa095aSDmitry Bezrukov 104633cd597fSDmitry Bezrukov /* Put PHY to low power*/ 104733cd597fSDmitry Bezrukov aqc111_data->phy_cfg |= AQ_LOW_POWER; 104833cd597fSDmitry Bezrukov aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0, 104933cd597fSDmitry Bezrukov &aqc111_data->phy_cfg); 105033cd597fSDmitry Bezrukov 10517b8b0654SDmitry Bezrukov netif_carrier_off(dev->net); 10527b8b0654SDmitry Bezrukov 1053f3aa095aSDmitry Bezrukov return 0; 10547cea2d40SDmitry Bezrukov } 10557cea2d40SDmitry Bezrukov 105602031466SDmitry Bezrukov static void aqc111_rx_checksum(struct sk_buff *skb, u64 pkt_desc) 105702031466SDmitry Bezrukov { 105802031466SDmitry Bezrukov u32 pkt_type = 0; 105902031466SDmitry Bezrukov 106002031466SDmitry Bezrukov skb->ip_summed = CHECKSUM_NONE; 106102031466SDmitry Bezrukov /* checksum error bit is set */ 106202031466SDmitry Bezrukov if (pkt_desc & AQ_RX_PD_L4_ERR || pkt_desc & AQ_RX_PD_L3_ERR) 106302031466SDmitry Bezrukov return; 106402031466SDmitry Bezrukov 106502031466SDmitry Bezrukov pkt_type = pkt_desc & AQ_RX_PD_L4_TYPE_MASK; 106602031466SDmitry Bezrukov /* It must be a TCP or UDP packet with a valid checksum */ 106702031466SDmitry Bezrukov if (pkt_type == AQ_RX_PD_L4_TCP || pkt_type == AQ_RX_PD_L4_UDP) 106802031466SDmitry Bezrukov skb->ip_summed = CHECKSUM_UNNECESSARY; 106902031466SDmitry Bezrukov } 107002031466SDmitry Bezrukov 1071361459cdSDmitry Bezrukov static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb) 1072361459cdSDmitry Bezrukov { 10736649d2a6SDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 1074361459cdSDmitry Bezrukov struct sk_buff *new_skb = NULL; 1075361459cdSDmitry Bezrukov u32 pkt_total_offset = 0; 1076361459cdSDmitry Bezrukov u64 *pkt_desc_ptr = NULL; 1077361459cdSDmitry Bezrukov u32 start_of_descs = 0; 1078361459cdSDmitry Bezrukov u32 desc_offset = 0; /*RX Header Offset*/ 1079361459cdSDmitry Bezrukov u16 pkt_count = 0; 1080361459cdSDmitry Bezrukov u64 desc_hdr = 0; 10817afa6c98SDmitry Bezrukov u16 vlan_tag = 0; 1082361459cdSDmitry Bezrukov u32 skb_len = 0; 1083361459cdSDmitry Bezrukov 1084361459cdSDmitry Bezrukov if (!skb) 1085361459cdSDmitry Bezrukov goto err; 1086361459cdSDmitry Bezrukov 1087361459cdSDmitry Bezrukov if (skb->len == 0) 1088361459cdSDmitry Bezrukov goto err; 1089361459cdSDmitry Bezrukov 1090361459cdSDmitry Bezrukov skb_len = skb->len; 1091361459cdSDmitry Bezrukov /* RX Descriptor Header */ 1092361459cdSDmitry Bezrukov skb_trim(skb, skb->len - sizeof(desc_hdr)); 1093361459cdSDmitry Bezrukov desc_hdr = le64_to_cpup((u64 *)skb_tail_pointer(skb)); 1094361459cdSDmitry Bezrukov 1095361459cdSDmitry Bezrukov /* Check these packets */ 1096361459cdSDmitry Bezrukov desc_offset = (desc_hdr & AQ_RX_DH_DESC_OFFSET_MASK) >> 1097361459cdSDmitry Bezrukov AQ_RX_DH_DESC_OFFSET_SHIFT; 1098361459cdSDmitry Bezrukov pkt_count = desc_hdr & AQ_RX_DH_PKT_CNT_MASK; 1099361459cdSDmitry Bezrukov start_of_descs = skb_len - ((pkt_count + 1) * sizeof(desc_hdr)); 1100361459cdSDmitry Bezrukov 1101361459cdSDmitry Bezrukov /* self check descs position */ 1102361459cdSDmitry Bezrukov if (start_of_descs != desc_offset) 1103361459cdSDmitry Bezrukov goto err; 1104361459cdSDmitry Bezrukov 1105361459cdSDmitry Bezrukov /* self check desc_offset from header*/ 1106361459cdSDmitry Bezrukov if (desc_offset >= skb_len) 1107361459cdSDmitry Bezrukov goto err; 1108361459cdSDmitry Bezrukov 1109361459cdSDmitry Bezrukov if (pkt_count == 0) 1110361459cdSDmitry Bezrukov goto err; 1111361459cdSDmitry Bezrukov 1112361459cdSDmitry Bezrukov /* Get the first RX packet descriptor */ 1113361459cdSDmitry Bezrukov pkt_desc_ptr = (u64 *)(skb->data + desc_offset); 1114361459cdSDmitry Bezrukov 1115361459cdSDmitry Bezrukov while (pkt_count--) { 1116361459cdSDmitry Bezrukov u64 pkt_desc = le64_to_cpup(pkt_desc_ptr); 1117361459cdSDmitry Bezrukov u32 pkt_len_with_padd = 0; 1118361459cdSDmitry Bezrukov u32 pkt_len = 0; 1119361459cdSDmitry Bezrukov 1120361459cdSDmitry Bezrukov pkt_len = (u32)((pkt_desc & AQ_RX_PD_LEN_MASK) >> 1121361459cdSDmitry Bezrukov AQ_RX_PD_LEN_SHIFT); 1122361459cdSDmitry Bezrukov pkt_len_with_padd = ((pkt_len + 7) & 0x7FFF8); 1123361459cdSDmitry Bezrukov 1124361459cdSDmitry Bezrukov pkt_total_offset += pkt_len_with_padd; 1125361459cdSDmitry Bezrukov if (pkt_total_offset > desc_offset || 1126361459cdSDmitry Bezrukov (pkt_count == 0 && pkt_total_offset != desc_offset)) { 1127361459cdSDmitry Bezrukov goto err; 1128361459cdSDmitry Bezrukov } 1129361459cdSDmitry Bezrukov 1130361459cdSDmitry Bezrukov if (pkt_desc & AQ_RX_PD_DROP || 1131361459cdSDmitry Bezrukov !(pkt_desc & AQ_RX_PD_RX_OK) || 1132361459cdSDmitry Bezrukov pkt_len > (dev->hard_mtu + AQ_RX_HW_PAD)) { 1133361459cdSDmitry Bezrukov skb_pull(skb, pkt_len_with_padd); 1134361459cdSDmitry Bezrukov /* Next RX Packet Descriptor */ 1135361459cdSDmitry Bezrukov pkt_desc_ptr++; 1136361459cdSDmitry Bezrukov continue; 1137361459cdSDmitry Bezrukov } 1138361459cdSDmitry Bezrukov 1139361459cdSDmitry Bezrukov /* Clone SKB */ 1140361459cdSDmitry Bezrukov new_skb = skb_clone(skb, GFP_ATOMIC); 1141361459cdSDmitry Bezrukov 1142361459cdSDmitry Bezrukov if (!new_skb) 1143361459cdSDmitry Bezrukov goto err; 1144361459cdSDmitry Bezrukov 1145361459cdSDmitry Bezrukov new_skb->len = pkt_len; 1146361459cdSDmitry Bezrukov skb_pull(new_skb, AQ_RX_HW_PAD); 1147361459cdSDmitry Bezrukov skb_set_tail_pointer(new_skb, new_skb->len); 1148361459cdSDmitry Bezrukov 1149361459cdSDmitry Bezrukov new_skb->truesize = SKB_TRUESIZE(new_skb->len); 11506649d2a6SDmitry Bezrukov if (aqc111_data->rx_checksum) 115102031466SDmitry Bezrukov aqc111_rx_checksum(new_skb, pkt_desc); 1152361459cdSDmitry Bezrukov 11537afa6c98SDmitry Bezrukov if (pkt_desc & AQ_RX_PD_VLAN) { 11547afa6c98SDmitry Bezrukov vlan_tag = pkt_desc >> AQ_RX_PD_VLAN_SHIFT; 11557afa6c98SDmitry Bezrukov __vlan_hwaccel_put_tag(new_skb, htons(ETH_P_8021Q), 11567afa6c98SDmitry Bezrukov vlan_tag & VLAN_VID_MASK); 11577afa6c98SDmitry Bezrukov } 11587afa6c98SDmitry Bezrukov 1159361459cdSDmitry Bezrukov usbnet_skb_return(dev, new_skb); 1160361459cdSDmitry Bezrukov if (pkt_count == 0) 1161361459cdSDmitry Bezrukov break; 1162361459cdSDmitry Bezrukov 1163361459cdSDmitry Bezrukov skb_pull(skb, pkt_len_with_padd); 1164361459cdSDmitry Bezrukov 1165361459cdSDmitry Bezrukov /* Next RX Packet Header */ 1166361459cdSDmitry Bezrukov pkt_desc_ptr++; 1167361459cdSDmitry Bezrukov 1168361459cdSDmitry Bezrukov new_skb = NULL; 1169361459cdSDmitry Bezrukov } 1170361459cdSDmitry Bezrukov 1171361459cdSDmitry Bezrukov return 1; 1172361459cdSDmitry Bezrukov 1173361459cdSDmitry Bezrukov err: 1174361459cdSDmitry Bezrukov return 0; 1175361459cdSDmitry Bezrukov } 1176361459cdSDmitry Bezrukov 11774a3576d2SDmitry Bezrukov static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb, 11784a3576d2SDmitry Bezrukov gfp_t flags) 11794a3576d2SDmitry Bezrukov { 11804a3576d2SDmitry Bezrukov int frame_size = dev->maxpacket; 11814a3576d2SDmitry Bezrukov struct sk_buff *new_skb = NULL; 11824a3576d2SDmitry Bezrukov u64 *tx_desc_ptr = NULL; 11834a3576d2SDmitry Bezrukov int padding_size = 0; 11844a3576d2SDmitry Bezrukov int headroom = 0; 11854a3576d2SDmitry Bezrukov int tailroom = 0; 11864a3576d2SDmitry Bezrukov u64 tx_desc = 0; 11877afa6c98SDmitry Bezrukov u16 tci = 0; 11884a3576d2SDmitry Bezrukov 11894a3576d2SDmitry Bezrukov /*Length of actual data*/ 11904a3576d2SDmitry Bezrukov tx_desc |= skb->len & AQ_TX_DESC_LEN_MASK; 11914a3576d2SDmitry Bezrukov 1192de074e7aSDmitry Bezrukov /* TSO MSS */ 1193de074e7aSDmitry Bezrukov tx_desc |= ((u64)(skb_shinfo(skb)->gso_size & AQ_TX_DESC_MSS_MASK)) << 1194de074e7aSDmitry Bezrukov AQ_TX_DESC_MSS_SHIFT; 1195de074e7aSDmitry Bezrukov 11964a3576d2SDmitry Bezrukov headroom = (skb->len + sizeof(tx_desc)) % 8; 11974a3576d2SDmitry Bezrukov if (headroom != 0) 11984a3576d2SDmitry Bezrukov padding_size = 8 - headroom; 11994a3576d2SDmitry Bezrukov 12004a3576d2SDmitry Bezrukov if (((skb->len + sizeof(tx_desc) + padding_size) % frame_size) == 0) { 12014a3576d2SDmitry Bezrukov padding_size += 8; 12024a3576d2SDmitry Bezrukov tx_desc |= AQ_TX_DESC_DROP_PADD; 12034a3576d2SDmitry Bezrukov } 12044a3576d2SDmitry Bezrukov 12057afa6c98SDmitry Bezrukov /* Vlan Tag */ 12067afa6c98SDmitry Bezrukov if (vlan_get_tag(skb, &tci) >= 0) { 12077afa6c98SDmitry Bezrukov tx_desc |= AQ_TX_DESC_VLAN; 12087afa6c98SDmitry Bezrukov tx_desc |= ((u64)tci & AQ_TX_DESC_VLAN_MASK) << 12097afa6c98SDmitry Bezrukov AQ_TX_DESC_VLAN_SHIFT; 12107afa6c98SDmitry Bezrukov } 12117afa6c98SDmitry Bezrukov 12124a3576d2SDmitry Bezrukov if (!dev->can_dma_sg && (dev->net->features & NETIF_F_SG) && 12134a3576d2SDmitry Bezrukov skb_linearize(skb)) 12144a3576d2SDmitry Bezrukov return NULL; 12154a3576d2SDmitry Bezrukov 12164a3576d2SDmitry Bezrukov headroom = skb_headroom(skb); 12174a3576d2SDmitry Bezrukov tailroom = skb_tailroom(skb); 12184a3576d2SDmitry Bezrukov 12194a3576d2SDmitry Bezrukov if (!(headroom >= sizeof(tx_desc) && tailroom >= padding_size)) { 12204a3576d2SDmitry Bezrukov new_skb = skb_copy_expand(skb, sizeof(tx_desc), 12214a3576d2SDmitry Bezrukov padding_size, flags); 12224a3576d2SDmitry Bezrukov dev_kfree_skb_any(skb); 12234a3576d2SDmitry Bezrukov skb = new_skb; 12244a3576d2SDmitry Bezrukov if (!skb) 12254a3576d2SDmitry Bezrukov return NULL; 12264a3576d2SDmitry Bezrukov } 12274a3576d2SDmitry Bezrukov if (padding_size != 0) 12284a3576d2SDmitry Bezrukov skb_put_zero(skb, padding_size); 12294a3576d2SDmitry Bezrukov /* Copy TX header */ 12304a3576d2SDmitry Bezrukov tx_desc_ptr = skb_push(skb, sizeof(tx_desc)); 12314a3576d2SDmitry Bezrukov *tx_desc_ptr = cpu_to_le64(tx_desc); 12324a3576d2SDmitry Bezrukov 12334a3576d2SDmitry Bezrukov usbnet_set_skb_tx_stats(skb, 1, 0); 12344a3576d2SDmitry Bezrukov 12354a3576d2SDmitry Bezrukov return skb; 12364a3576d2SDmitry Bezrukov } 12374a3576d2SDmitry Bezrukov 123817364b80SDmitry Bezrukov static const struct driver_info aqc111_info = { 123917364b80SDmitry Bezrukov .description = "Aquantia AQtion USB to 5GbE Controller", 12407cea2d40SDmitry Bezrukov .bind = aqc111_bind, 12417cea2d40SDmitry Bezrukov .unbind = aqc111_unbind, 12427b8b0654SDmitry Bezrukov .status = aqc111_status, 12437b8b0654SDmitry Bezrukov .link_reset = aqc111_link_reset, 1244f3aa095aSDmitry Bezrukov .reset = aqc111_reset, 1245f3aa095aSDmitry Bezrukov .stop = aqc111_stop, 12464a3576d2SDmitry Bezrukov .flags = FLAG_ETHER | FLAG_FRAMING_AX | 12474a3576d2SDmitry Bezrukov FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET, 1248361459cdSDmitry Bezrukov .rx_fixup = aqc111_rx_fixup, 12494a3576d2SDmitry Bezrukov .tx_fixup = aqc111_tx_fixup, 125017364b80SDmitry Bezrukov }; 125117364b80SDmitry Bezrukov 1252fa61ce4dSDmitry Bezrukov #define ASIX111_DESC \ 1253fa61ce4dSDmitry Bezrukov "ASIX USB 3.1 Gen1 to 5G Multi-Gigabit Ethernet Adapter" 1254fa61ce4dSDmitry Bezrukov 1255fa61ce4dSDmitry Bezrukov static const struct driver_info asix111_info = { 1256fa61ce4dSDmitry Bezrukov .description = ASIX111_DESC, 1257fa61ce4dSDmitry Bezrukov .bind = aqc111_bind, 1258fa61ce4dSDmitry Bezrukov .unbind = aqc111_unbind, 1259fa61ce4dSDmitry Bezrukov .status = aqc111_status, 1260fa61ce4dSDmitry Bezrukov .link_reset = aqc111_link_reset, 1261fa61ce4dSDmitry Bezrukov .reset = aqc111_reset, 1262fa61ce4dSDmitry Bezrukov .stop = aqc111_stop, 1263fa61ce4dSDmitry Bezrukov .flags = FLAG_ETHER | FLAG_FRAMING_AX | 1264fa61ce4dSDmitry Bezrukov FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET, 1265fa61ce4dSDmitry Bezrukov .rx_fixup = aqc111_rx_fixup, 1266fa61ce4dSDmitry Bezrukov .tx_fixup = aqc111_tx_fixup, 1267fa61ce4dSDmitry Bezrukov }; 1268fa61ce4dSDmitry Bezrukov 1269fa61ce4dSDmitry Bezrukov #undef ASIX111_DESC 1270fa61ce4dSDmitry Bezrukov 1271fa61ce4dSDmitry Bezrukov #define ASIX112_DESC \ 1272fa61ce4dSDmitry Bezrukov "ASIX USB 3.1 Gen1 to 2.5G Multi-Gigabit Ethernet Adapter" 1273fa61ce4dSDmitry Bezrukov 1274fa61ce4dSDmitry Bezrukov static const struct driver_info asix112_info = { 1275fa61ce4dSDmitry Bezrukov .description = ASIX112_DESC, 1276fa61ce4dSDmitry Bezrukov .bind = aqc111_bind, 1277fa61ce4dSDmitry Bezrukov .unbind = aqc111_unbind, 1278fa61ce4dSDmitry Bezrukov .status = aqc111_status, 1279fa61ce4dSDmitry Bezrukov .link_reset = aqc111_link_reset, 1280fa61ce4dSDmitry Bezrukov .reset = aqc111_reset, 1281fa61ce4dSDmitry Bezrukov .stop = aqc111_stop, 1282fa61ce4dSDmitry Bezrukov .flags = FLAG_ETHER | FLAG_FRAMING_AX | 1283fa61ce4dSDmitry Bezrukov FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET, 1284fa61ce4dSDmitry Bezrukov .rx_fixup = aqc111_rx_fixup, 1285fa61ce4dSDmitry Bezrukov .tx_fixup = aqc111_tx_fixup, 1286fa61ce4dSDmitry Bezrukov }; 1287fa61ce4dSDmitry Bezrukov 1288fa61ce4dSDmitry Bezrukov #undef ASIX112_DESC 1289fa61ce4dSDmitry Bezrukov 1290*9098f21fSDmitry Bezrukov static const struct driver_info trendnet_info = { 1291*9098f21fSDmitry Bezrukov .description = "USB-C 3.1 to 5GBASE-T Ethernet Adapter", 1292*9098f21fSDmitry Bezrukov .bind = aqc111_bind, 1293*9098f21fSDmitry Bezrukov .unbind = aqc111_unbind, 1294*9098f21fSDmitry Bezrukov .status = aqc111_status, 1295*9098f21fSDmitry Bezrukov .link_reset = aqc111_link_reset, 1296*9098f21fSDmitry Bezrukov .reset = aqc111_reset, 1297*9098f21fSDmitry Bezrukov .stop = aqc111_stop, 1298*9098f21fSDmitry Bezrukov .flags = FLAG_ETHER | FLAG_FRAMING_AX | 1299*9098f21fSDmitry Bezrukov FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET, 1300*9098f21fSDmitry Bezrukov .rx_fixup = aqc111_rx_fixup, 1301*9098f21fSDmitry Bezrukov .tx_fixup = aqc111_tx_fixup, 1302*9098f21fSDmitry Bezrukov }; 1303*9098f21fSDmitry Bezrukov 1304e58ba454SDmitry Bezrukov static int aqc111_suspend(struct usb_interface *intf, pm_message_t message) 1305e58ba454SDmitry Bezrukov { 1306e58ba454SDmitry Bezrukov struct usbnet *dev = usb_get_intfdata(intf); 1307e58ba454SDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 1308e58ba454SDmitry Bezrukov u16 temp_rx_ctrl = 0x00; 1309e58ba454SDmitry Bezrukov u16 reg16; 1310e58ba454SDmitry Bezrukov u8 reg8; 1311e58ba454SDmitry Bezrukov 1312e58ba454SDmitry Bezrukov usbnet_suspend(intf, message); 1313e58ba454SDmitry Bezrukov 1314e58ba454SDmitry Bezrukov aqc111_read16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, ®16); 1315e58ba454SDmitry Bezrukov temp_rx_ctrl = reg16; 1316e58ba454SDmitry Bezrukov /* Stop RX operations*/ 1317e58ba454SDmitry Bezrukov reg16 &= ~SFR_RX_CTL_START; 1318e58ba454SDmitry Bezrukov aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, ®16); 1319e58ba454SDmitry Bezrukov /* Force bz */ 1320e58ba454SDmitry Bezrukov aqc111_read16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL, 1321e58ba454SDmitry Bezrukov 2, ®16); 1322e58ba454SDmitry Bezrukov reg16 |= SFR_PHYPWR_RSTCTL_BZ; 1323e58ba454SDmitry Bezrukov aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL, 1324e58ba454SDmitry Bezrukov 2, ®16); 1325e58ba454SDmitry Bezrukov 1326e58ba454SDmitry Bezrukov reg8 = SFR_BULK_OUT_EFF_EN; 1327e58ba454SDmitry Bezrukov aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL, 1328e58ba454SDmitry Bezrukov 1, 1, ®8); 1329e58ba454SDmitry Bezrukov 1330e58ba454SDmitry Bezrukov temp_rx_ctrl &= ~(SFR_RX_CTL_START | SFR_RX_CTL_RF_WAK | 1331e58ba454SDmitry Bezrukov SFR_RX_CTL_AP | SFR_RX_CTL_AM); 1332e58ba454SDmitry Bezrukov aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 1333e58ba454SDmitry Bezrukov 2, &temp_rx_ctrl); 1334e58ba454SDmitry Bezrukov 1335e58ba454SDmitry Bezrukov reg8 = 0x00; 1336e58ba454SDmitry Bezrukov aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH, 1337e58ba454SDmitry Bezrukov 1, 1, ®8); 1338e58ba454SDmitry Bezrukov 1339e58ba454SDmitry Bezrukov if (aqc111_data->wol_flags) { 134097e6c858SNathan Chancellor struct aqc111_wol_cfg wol_cfg; 134197e6c858SNathan Chancellor 134297e6c858SNathan Chancellor memset(&wol_cfg, 0, sizeof(struct aqc111_wol_cfg)); 1343e58ba454SDmitry Bezrukov 1344e58ba454SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_WOL; 1345e58ba454SDmitry Bezrukov ether_addr_copy(wol_cfg.hw_addr, dev->net->dev_addr); 1346e58ba454SDmitry Bezrukov wol_cfg.flags = aqc111_data->wol_flags; 1347e58ba454SDmitry Bezrukov 1348e58ba454SDmitry Bezrukov temp_rx_ctrl |= (SFR_RX_CTL_AB | SFR_RX_CTL_START); 1349e58ba454SDmitry Bezrukov aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 1350e58ba454SDmitry Bezrukov 2, &temp_rx_ctrl); 1351e58ba454SDmitry Bezrukov reg8 = 0x00; 1352e58ba454SDmitry Bezrukov aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK, 1353e58ba454SDmitry Bezrukov 1, 1, ®8); 1354e58ba454SDmitry Bezrukov reg8 = SFR_BMRX_DMA_EN; 1355e58ba454SDmitry Bezrukov aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BMRX_DMA_CONTROL, 1356e58ba454SDmitry Bezrukov 1, 1, ®8); 1357e58ba454SDmitry Bezrukov reg8 = SFR_RX_PATH_READY; 1358e58ba454SDmitry Bezrukov aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH, 1359e58ba454SDmitry Bezrukov 1, 1, ®8); 1360e58ba454SDmitry Bezrukov reg8 = 0x07; 1361e58ba454SDmitry Bezrukov aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QCTRL, 1362e58ba454SDmitry Bezrukov 1, 1, ®8); 1363e58ba454SDmitry Bezrukov reg8 = 0x00; 1364e58ba454SDmitry Bezrukov aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, 1365e58ba454SDmitry Bezrukov SFR_RX_BULKIN_QTIMR_LOW, 1, 1, ®8); 1366e58ba454SDmitry Bezrukov aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, 1367e58ba454SDmitry Bezrukov SFR_RX_BULKIN_QTIMR_HIGH, 1, 1, ®8); 1368e58ba454SDmitry Bezrukov reg8 = 0xFF; 1369e58ba454SDmitry Bezrukov aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QSIZE, 1370e58ba454SDmitry Bezrukov 1, 1, ®8); 1371e58ba454SDmitry Bezrukov aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QIFG, 1372e58ba454SDmitry Bezrukov 1, 1, ®8); 1373e58ba454SDmitry Bezrukov 1374e58ba454SDmitry Bezrukov aqc111_read16_cmd_nopm(dev, AQ_ACCESS_MAC, 1375e58ba454SDmitry Bezrukov SFR_MEDIUM_STATUS_MODE, 2, ®16); 1376e58ba454SDmitry Bezrukov reg16 |= SFR_MEDIUM_RECEIVE_EN; 1377e58ba454SDmitry Bezrukov aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, 1378e58ba454SDmitry Bezrukov SFR_MEDIUM_STATUS_MODE, 2, ®16); 1379e58ba454SDmitry Bezrukov 1380e58ba454SDmitry Bezrukov aqc111_write_cmd(dev, AQ_WOL_CFG, 0, 0, 1381e58ba454SDmitry Bezrukov WOL_CFG_SIZE, &wol_cfg); 1382e58ba454SDmitry Bezrukov aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0, 1383e58ba454SDmitry Bezrukov &aqc111_data->phy_cfg); 1384e58ba454SDmitry Bezrukov } else { 1385e58ba454SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_LOW_POWER; 1386e58ba454SDmitry Bezrukov aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0, 1387e58ba454SDmitry Bezrukov &aqc111_data->phy_cfg); 1388e58ba454SDmitry Bezrukov 1389e58ba454SDmitry Bezrukov /* Disable RX path */ 1390e58ba454SDmitry Bezrukov aqc111_read16_cmd_nopm(dev, AQ_ACCESS_MAC, 1391e58ba454SDmitry Bezrukov SFR_MEDIUM_STATUS_MODE, 2, ®16); 1392e58ba454SDmitry Bezrukov reg16 &= ~SFR_MEDIUM_RECEIVE_EN; 1393e58ba454SDmitry Bezrukov aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, 1394e58ba454SDmitry Bezrukov SFR_MEDIUM_STATUS_MODE, 2, ®16); 1395e58ba454SDmitry Bezrukov } 1396e58ba454SDmitry Bezrukov 1397e58ba454SDmitry Bezrukov return 0; 1398e58ba454SDmitry Bezrukov } 1399e58ba454SDmitry Bezrukov 1400e58ba454SDmitry Bezrukov static int aqc111_resume(struct usb_interface *intf) 1401e58ba454SDmitry Bezrukov { 1402e58ba454SDmitry Bezrukov struct usbnet *dev = usb_get_intfdata(intf); 1403e58ba454SDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 1404e58ba454SDmitry Bezrukov u16 reg16; 1405e58ba454SDmitry Bezrukov u8 reg8; 1406e58ba454SDmitry Bezrukov 1407e58ba454SDmitry Bezrukov netif_carrier_off(dev->net); 1408e58ba454SDmitry Bezrukov 1409e58ba454SDmitry Bezrukov /* Power up ethernet PHY */ 1410e58ba454SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_PHY_POWER_EN; 1411e58ba454SDmitry Bezrukov aqc111_data->phy_cfg &= ~AQ_LOW_POWER; 1412e58ba454SDmitry Bezrukov aqc111_data->phy_cfg &= ~AQ_WOL; 1413e58ba454SDmitry Bezrukov 1414e58ba454SDmitry Bezrukov reg8 = 0xFF; 1415e58ba454SDmitry Bezrukov aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK, 1416e58ba454SDmitry Bezrukov 1, 1, ®8); 1417e58ba454SDmitry Bezrukov /* Configure RX control register => start operation */ 1418e58ba454SDmitry Bezrukov reg16 = aqc111_data->rxctl; 1419e58ba454SDmitry Bezrukov reg16 &= ~SFR_RX_CTL_START; 1420e58ba454SDmitry Bezrukov aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, ®16); 1421e58ba454SDmitry Bezrukov 1422e58ba454SDmitry Bezrukov reg16 |= SFR_RX_CTL_START; 1423e58ba454SDmitry Bezrukov aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, ®16); 1424e58ba454SDmitry Bezrukov 1425e58ba454SDmitry Bezrukov aqc111_set_phy_speed(dev, aqc111_data->autoneg, 1426e58ba454SDmitry Bezrukov aqc111_data->advertised_speed); 1427e58ba454SDmitry Bezrukov 1428e58ba454SDmitry Bezrukov aqc111_read16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 1429e58ba454SDmitry Bezrukov 2, ®16); 1430e58ba454SDmitry Bezrukov reg16 |= SFR_MEDIUM_RECEIVE_EN; 1431e58ba454SDmitry Bezrukov aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 1432e58ba454SDmitry Bezrukov 2, ®16); 1433e58ba454SDmitry Bezrukov reg8 = SFR_RX_PATH_READY; 1434e58ba454SDmitry Bezrukov aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH, 1435e58ba454SDmitry Bezrukov 1, 1, ®8); 1436e58ba454SDmitry Bezrukov reg8 = 0x0; 1437e58ba454SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BMRX_DMA_CONTROL, 1, 1, ®8); 1438e58ba454SDmitry Bezrukov 1439e58ba454SDmitry Bezrukov return usbnet_resume(intf); 1440e58ba454SDmitry Bezrukov } 1441e58ba454SDmitry Bezrukov 144217364b80SDmitry Bezrukov #define AQC111_USB_ETH_DEV(vid, pid, table) \ 144317364b80SDmitry Bezrukov USB_DEVICE_INTERFACE_CLASS((vid), (pid), USB_CLASS_VENDOR_SPEC), \ 144417364b80SDmitry Bezrukov .driver_info = (unsigned long)&(table) \ 144517364b80SDmitry Bezrukov }, \ 144617364b80SDmitry Bezrukov { \ 144717364b80SDmitry Bezrukov USB_DEVICE_AND_INTERFACE_INFO((vid), (pid), \ 144817364b80SDmitry Bezrukov USB_CLASS_COMM, \ 144917364b80SDmitry Bezrukov USB_CDC_SUBCLASS_ETHERNET, \ 145017364b80SDmitry Bezrukov USB_CDC_PROTO_NONE), \ 145117364b80SDmitry Bezrukov .driver_info = (unsigned long)&(table), 145217364b80SDmitry Bezrukov 145317364b80SDmitry Bezrukov static const struct usb_device_id products[] = { 145417364b80SDmitry Bezrukov {AQC111_USB_ETH_DEV(0x2eca, 0xc101, aqc111_info)}, 1455fa61ce4dSDmitry Bezrukov {AQC111_USB_ETH_DEV(0x0b95, 0x2790, asix111_info)}, 1456fa61ce4dSDmitry Bezrukov {AQC111_USB_ETH_DEV(0x0b95, 0x2791, asix112_info)}, 1457*9098f21fSDmitry Bezrukov {AQC111_USB_ETH_DEV(0x20f4, 0xe05a, trendnet_info)}, 145817364b80SDmitry Bezrukov { },/* END */ 145917364b80SDmitry Bezrukov }; 146017364b80SDmitry Bezrukov MODULE_DEVICE_TABLE(usb, products); 146117364b80SDmitry Bezrukov 146217364b80SDmitry Bezrukov static struct usb_driver aq_driver = { 146317364b80SDmitry Bezrukov .name = "aqc111", 146417364b80SDmitry Bezrukov .id_table = products, 146517364b80SDmitry Bezrukov .probe = usbnet_probe, 1466e58ba454SDmitry Bezrukov .suspend = aqc111_suspend, 1467e58ba454SDmitry Bezrukov .resume = aqc111_resume, 146817364b80SDmitry Bezrukov .disconnect = usbnet_disconnect, 146917364b80SDmitry Bezrukov }; 147017364b80SDmitry Bezrukov 147117364b80SDmitry Bezrukov module_usb_driver(aq_driver); 147217364b80SDmitry Bezrukov 147317364b80SDmitry Bezrukov MODULE_DESCRIPTION("Aquantia AQtion USB to 5/2.5GbE Controllers"); 147417364b80SDmitry Bezrukov MODULE_LICENSE("GPL"); 1475