diff options
Diffstat (limited to 'drivers/net/usb/asix.c')
-rw-r--r-- | drivers/net/usb/asix.c | 458 |
1 files changed, 277 insertions, 181 deletions
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index c5c4b4def7fb..e6fed4d4cb77 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c | |||
@@ -36,8 +36,8 @@ | |||
36 | #include <linux/usb/usbnet.h> | 36 | #include <linux/usb/usbnet.h> |
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | 38 | ||
39 | #define DRIVER_VERSION "14-Jun-2006" | 39 | #define DRIVER_VERSION "08-Nov-2011" |
40 | static const char driver_name [] = "asix"; | 40 | #define DRIVER_NAME "asix" |
41 | 41 | ||
42 | /* ASIX AX8817X based USB 2.0 Ethernet Devices */ | 42 | /* ASIX AX8817X based USB 2.0 Ethernet Devices */ |
43 | 43 | ||
@@ -115,28 +115,27 @@ static const char driver_name [] = "asix"; | |||
115 | #define AX88178_MEDIUM_DEFAULT \ | 115 | #define AX88178_MEDIUM_DEFAULT \ |
116 | (AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \ | 116 | (AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \ |
117 | AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \ | 117 | AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \ |
118 | AX_MEDIUM_RE ) | 118 | AX_MEDIUM_RE) |
119 | 119 | ||
120 | #define AX88772_MEDIUM_DEFAULT \ | 120 | #define AX88772_MEDIUM_DEFAULT \ |
121 | (AX_MEDIUM_FD | AX_MEDIUM_RFC | \ | 121 | (AX_MEDIUM_FD | AX_MEDIUM_RFC | \ |
122 | AX_MEDIUM_TFC | AX_MEDIUM_PS | \ | 122 | AX_MEDIUM_TFC | AX_MEDIUM_PS | \ |
123 | AX_MEDIUM_AC | AX_MEDIUM_RE ) | 123 | AX_MEDIUM_AC | AX_MEDIUM_RE) |
124 | 124 | ||
125 | /* AX88772 & AX88178 RX_CTL values */ | 125 | /* AX88772 & AX88178 RX_CTL values */ |
126 | #define AX_RX_CTL_SO 0x0080 | 126 | #define AX_RX_CTL_SO 0x0080 |
127 | #define AX_RX_CTL_AP 0x0020 | 127 | #define AX_RX_CTL_AP 0x0020 |
128 | #define AX_RX_CTL_AM 0x0010 | 128 | #define AX_RX_CTL_AM 0x0010 |
129 | #define AX_RX_CTL_AB 0x0008 | 129 | #define AX_RX_CTL_AB 0x0008 |
130 | #define AX_RX_CTL_SEP 0x0004 | 130 | #define AX_RX_CTL_SEP 0x0004 |
131 | #define AX_RX_CTL_AMALL 0x0002 | 131 | #define AX_RX_CTL_AMALL 0x0002 |
132 | #define AX_RX_CTL_PRO 0x0001 | 132 | #define AX_RX_CTL_PRO 0x0001 |
133 | #define AX_RX_CTL_MFB_2048 0x0000 | 133 | #define AX_RX_CTL_MFB_2048 0x0000 |
134 | #define AX_RX_CTL_MFB_4096 0x0100 | 134 | #define AX_RX_CTL_MFB_4096 0x0100 |
135 | #define AX_RX_CTL_MFB_8192 0x0200 | 135 | #define AX_RX_CTL_MFB_8192 0x0200 |
136 | #define AX_RX_CTL_MFB_16384 0x0300 | 136 | #define AX_RX_CTL_MFB_16384 0x0300 |
137 | 137 | ||
138 | #define AX_DEFAULT_RX_CTL \ | 138 | #define AX_DEFAULT_RX_CTL (AX_RX_CTL_SO | AX_RX_CTL_AB) |
139 | (AX_RX_CTL_SO | AX_RX_CTL_AB ) | ||
140 | 139 | ||
141 | /* GPIO 0 .. 2 toggles */ | 140 | /* GPIO 0 .. 2 toggles */ |
142 | #define AX_GPIO_GPO0EN 0x01 /* GPIO0 Output enable */ | 141 | #define AX_GPIO_GPO0EN 0x01 /* GPIO0 Output enable */ |
@@ -164,6 +163,8 @@ static const char driver_name [] = "asix"; | |||
164 | #define MARVELL_CTRL_TXDELAY 0x0002 | 163 | #define MARVELL_CTRL_TXDELAY 0x0002 |
165 | #define MARVELL_CTRL_RXDELAY 0x0080 | 164 | #define MARVELL_CTRL_RXDELAY 0x0080 |
166 | 165 | ||
166 | #define PHY_MODE_RTL8211CL 0x000C | ||
167 | |||
167 | /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ | 168 | /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ |
168 | struct asix_data { | 169 | struct asix_data { |
169 | u8 multi_filter[AX_MCAST_FILTER_SIZE]; | 170 | u8 multi_filter[AX_MCAST_FILTER_SIZE]; |
@@ -268,12 +269,15 @@ asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index, | |||
268 | 269 | ||
269 | netdev_dbg(dev->net, "asix_write_cmd_async() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n", | 270 | netdev_dbg(dev->net, "asix_write_cmd_async() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n", |
270 | cmd, value, index, size); | 271 | cmd, value, index, size); |
271 | if ((urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) { | 272 | |
273 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
274 | if (!urb) { | ||
272 | netdev_err(dev->net, "Error allocating URB in write_cmd_async!\n"); | 275 | netdev_err(dev->net, "Error allocating URB in write_cmd_async!\n"); |
273 | return; | 276 | return; |
274 | } | 277 | } |
275 | 278 | ||
276 | if ((req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC)) == NULL) { | 279 | req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC); |
280 | if (!req) { | ||
277 | netdev_err(dev->net, "Failed to allocate memory for control request\n"); | 281 | netdev_err(dev->net, "Failed to allocate memory for control request\n"); |
278 | usb_free_urb(urb); | 282 | usb_free_urb(urb); |
279 | return; | 283 | return; |
@@ -290,7 +294,8 @@ asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index, | |||
290 | (void *)req, data, size, | 294 | (void *)req, data, size, |
291 | asix_async_cmd_callback, req); | 295 | asix_async_cmd_callback, req); |
292 | 296 | ||
293 | if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { | 297 | status = usb_submit_urb(urb, GFP_ATOMIC); |
298 | if (status < 0) { | ||
294 | netdev_err(dev->net, "Error submitting the control message: status=%d\n", | 299 | netdev_err(dev->net, "Error submitting the control message: status=%d\n", |
295 | status); | 300 | status); |
296 | kfree(req); | 301 | kfree(req); |
@@ -531,11 +536,11 @@ static u16 asix_read_medium_status(struct usbnet *dev) | |||
531 | if (ret < 0) { | 536 | if (ret < 0) { |
532 | netdev_err(dev->net, "Error reading Medium Status register: %02x\n", | 537 | netdev_err(dev->net, "Error reading Medium Status register: %02x\n", |
533 | ret); | 538 | ret); |
534 | goto out; | 539 | return ret; /* TODO: callers not checking for error ret */ |
535 | } | 540 | } |
536 | ret = le16_to_cpu(v); | 541 | |
537 | out: | 542 | return le16_to_cpu(v); |
538 | return ret; | 543 | |
539 | } | 544 | } |
540 | 545 | ||
541 | static int asix_write_medium_mode(struct usbnet *dev, u16 mode) | 546 | static int asix_write_medium_mode(struct usbnet *dev, u16 mode) |
@@ -647,9 +652,17 @@ static u32 asix_get_phyid(struct usbnet *dev) | |||
647 | { | 652 | { |
648 | int phy_reg; | 653 | int phy_reg; |
649 | u32 phy_id; | 654 | u32 phy_id; |
655 | int i; | ||
650 | 656 | ||
651 | phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1); | 657 | /* Poll for the rare case the FW or phy isn't ready yet. */ |
652 | if (phy_reg < 0) | 658 | for (i = 0; i < 100; i++) { |
659 | phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1); | ||
660 | if (phy_reg != 0 && phy_reg != 0xFFFF) | ||
661 | break; | ||
662 | mdelay(1); | ||
663 | } | ||
664 | |||
665 | if (phy_reg <= 0 || phy_reg == 0xFFFF) | ||
653 | return 0; | 666 | return 0; |
654 | 667 | ||
655 | phy_id = (phy_reg & 0xffff) << 16; | 668 | phy_id = (phy_reg & 0xffff) << 16; |
@@ -676,12 +689,6 @@ asix_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) | |||
676 | } | 689 | } |
677 | wolinfo->supported = WAKE_PHY | WAKE_MAGIC; | 690 | wolinfo->supported = WAKE_PHY | WAKE_MAGIC; |
678 | wolinfo->wolopts = 0; | 691 | wolinfo->wolopts = 0; |
679 | if (opt & AX_MONITOR_MODE) { | ||
680 | if (opt & AX_MONITOR_LINK) | ||
681 | wolinfo->wolopts |= WAKE_PHY; | ||
682 | if (opt & AX_MONITOR_MAGIC) | ||
683 | wolinfo->wolopts |= WAKE_MAGIC; | ||
684 | } | ||
685 | } | 692 | } |
686 | 693 | ||
687 | static int | 694 | static int |
@@ -694,8 +701,6 @@ asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) | |||
694 | opt |= AX_MONITOR_LINK; | 701 | opt |= AX_MONITOR_LINK; |
695 | if (wolinfo->wolopts & WAKE_MAGIC) | 702 | if (wolinfo->wolopts & WAKE_MAGIC) |
696 | opt |= AX_MONITOR_MAGIC; | 703 | opt |= AX_MONITOR_MAGIC; |
697 | if (opt != 0) | ||
698 | opt |= AX_MONITOR_MODE; | ||
699 | 704 | ||
700 | if (asix_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE, | 705 | if (asix_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE, |
701 | opt, 0, 0, NULL) < 0) | 706 | opt, 0, 0, NULL) < 0) |
@@ -744,7 +749,7 @@ static void asix_get_drvinfo (struct net_device *net, | |||
744 | 749 | ||
745 | /* Inherit standard device info */ | 750 | /* Inherit standard device info */ |
746 | usbnet_get_drvinfo(net, info); | 751 | usbnet_get_drvinfo(net, info); |
747 | strncpy (info->driver, driver_name, sizeof info->driver); | 752 | strncpy (info->driver, DRIVER_NAME, sizeof info->driver); |
748 | strncpy (info->version, DRIVER_VERSION, sizeof info->version); | 753 | strncpy (info->version, DRIVER_VERSION, sizeof info->version); |
749 | info->eedump_len = data->eeprom_len; | 754 | info->eedump_len = data->eeprom_len; |
750 | } | 755 | } |
@@ -872,7 +877,7 @@ static const struct net_device_ops ax88172_netdev_ops = { | |||
872 | .ndo_set_mac_address = eth_mac_addr, | 877 | .ndo_set_mac_address = eth_mac_addr, |
873 | .ndo_validate_addr = eth_validate_addr, | 878 | .ndo_validate_addr = eth_validate_addr, |
874 | .ndo_do_ioctl = asix_ioctl, | 879 | .ndo_do_ioctl = asix_ioctl, |
875 | .ndo_set_multicast_list = ax88172_set_multicast, | 880 | .ndo_set_rx_mode = ax88172_set_multicast, |
876 | }; | 881 | }; |
877 | 882 | ||
878 | static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf) | 883 | static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf) |
@@ -889,19 +894,20 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf) | |||
889 | 894 | ||
890 | /* Toggle the GPIOs in a manufacturer/model specific way */ | 895 | /* Toggle the GPIOs in a manufacturer/model specific way */ |
891 | for (i = 2; i >= 0; i--) { | 896 | for (i = 2; i >= 0; i--) { |
892 | if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, | 897 | ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, |
893 | (gpio_bits >> (i * 8)) & 0xff, 0, 0, | 898 | (gpio_bits >> (i * 8)) & 0xff, 0, 0, NULL); |
894 | NULL)) < 0) | 899 | if (ret < 0) |
895 | goto out; | 900 | goto out; |
896 | msleep(5); | 901 | msleep(5); |
897 | } | 902 | } |
898 | 903 | ||
899 | if ((ret = asix_write_rx_ctl(dev, 0x80)) < 0) | 904 | ret = asix_write_rx_ctl(dev, 0x80); |
905 | if (ret < 0) | ||
900 | goto out; | 906 | goto out; |
901 | 907 | ||
902 | /* Get the MAC address */ | 908 | /* Get the MAC address */ |
903 | if ((ret = asix_read_cmd(dev, AX88172_CMD_READ_NODE_ID, | 909 | ret = asix_read_cmd(dev, AX88172_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf); |
904 | 0, 0, ETH_ALEN, buf)) < 0) { | 910 | if (ret < 0) { |
905 | dbg("read AX_CMD_READ_NODE_ID failed: %d", ret); | 911 | dbg("read AX_CMD_READ_NODE_ID failed: %d", ret); |
906 | goto out; | 912 | goto out; |
907 | } | 913 | } |
@@ -966,117 +972,88 @@ static int ax88772_link_reset(struct usbnet *dev) | |||
966 | return 0; | 972 | return 0; |
967 | } | 973 | } |
968 | 974 | ||
969 | static const struct net_device_ops ax88772_netdev_ops = { | 975 | static int ax88772_reset(struct usbnet *dev) |
970 | .ndo_open = usbnet_open, | ||
971 | .ndo_stop = usbnet_stop, | ||
972 | .ndo_start_xmit = usbnet_start_xmit, | ||
973 | .ndo_tx_timeout = usbnet_tx_timeout, | ||
974 | .ndo_change_mtu = usbnet_change_mtu, | ||
975 | .ndo_set_mac_address = asix_set_mac_address, | ||
976 | .ndo_validate_addr = eth_validate_addr, | ||
977 | .ndo_do_ioctl = asix_ioctl, | ||
978 | .ndo_set_multicast_list = asix_set_multicast, | ||
979 | }; | ||
980 | |||
981 | static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) | ||
982 | { | 976 | { |
983 | int ret, embd_phy; | 977 | int ret, embd_phy; |
984 | u16 rx_ctl; | 978 | u16 rx_ctl; |
985 | struct asix_data *data = (struct asix_data *)&dev->data; | ||
986 | u8 buf[ETH_ALEN]; | ||
987 | u32 phyid; | ||
988 | |||
989 | data->eeprom_len = AX88772_EEPROM_LEN; | ||
990 | 979 | ||
991 | usbnet_get_endpoints(dev,intf); | 980 | ret = asix_write_gpio(dev, |
992 | 981 | AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5); | |
993 | if ((ret = asix_write_gpio(dev, | 982 | if (ret < 0) |
994 | AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5)) < 0) | ||
995 | goto out; | 983 | goto out; |
996 | 984 | ||
997 | /* 0x10 is the phy id of the embedded 10/100 ethernet phy */ | ||
998 | embd_phy = ((asix_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0); | 985 | embd_phy = ((asix_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0); |
999 | if ((ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, | 986 | |
1000 | embd_phy, 0, 0, NULL)) < 0) { | 987 | ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL); |
988 | if (ret < 0) { | ||
1001 | dbg("Select PHY #1 failed: %d", ret); | 989 | dbg("Select PHY #1 failed: %d", ret); |
1002 | goto out; | 990 | goto out; |
1003 | } | 991 | } |
1004 | 992 | ||
1005 | if ((ret = asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL)) < 0) | 993 | ret = asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL); |
994 | if (ret < 0) | ||
1006 | goto out; | 995 | goto out; |
1007 | 996 | ||
1008 | msleep(150); | 997 | msleep(150); |
1009 | if ((ret = asix_sw_reset(dev, AX_SWRESET_CLEAR)) < 0) | 998 | |
999 | ret = asix_sw_reset(dev, AX_SWRESET_CLEAR); | ||
1000 | if (ret < 0) | ||
1010 | goto out; | 1001 | goto out; |
1011 | 1002 | ||
1012 | msleep(150); | 1003 | msleep(150); |
1004 | |||
1013 | if (embd_phy) { | 1005 | if (embd_phy) { |
1014 | if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL)) < 0) | 1006 | ret = asix_sw_reset(dev, AX_SWRESET_IPRL); |
1007 | if (ret < 0) | ||
1015 | goto out; | 1008 | goto out; |
1016 | } | 1009 | } else { |
1017 | else { | 1010 | ret = asix_sw_reset(dev, AX_SWRESET_PRTE); |
1018 | if ((ret = asix_sw_reset(dev, AX_SWRESET_PRTE)) < 0) | 1011 | if (ret < 0) |
1019 | goto out; | 1012 | goto out; |
1020 | } | 1013 | } |
1021 | 1014 | ||
1022 | msleep(150); | 1015 | msleep(150); |
1023 | rx_ctl = asix_read_rx_ctl(dev); | 1016 | rx_ctl = asix_read_rx_ctl(dev); |
1024 | dbg("RX_CTL is 0x%04x after software reset", rx_ctl); | 1017 | dbg("RX_CTL is 0x%04x after software reset", rx_ctl); |
1025 | if ((ret = asix_write_rx_ctl(dev, 0x0000)) < 0) | 1018 | ret = asix_write_rx_ctl(dev, 0x0000); |
1019 | if (ret < 0) | ||
1026 | goto out; | 1020 | goto out; |
1027 | 1021 | ||
1028 | rx_ctl = asix_read_rx_ctl(dev); | 1022 | rx_ctl = asix_read_rx_ctl(dev); |
1029 | dbg("RX_CTL is 0x%04x setting to 0x0000", rx_ctl); | 1023 | dbg("RX_CTL is 0x%04x setting to 0x0000", rx_ctl); |
1030 | 1024 | ||
1031 | /* Get the MAC address */ | 1025 | ret = asix_sw_reset(dev, AX_SWRESET_PRL); |
1032 | if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, | 1026 | if (ret < 0) |
1033 | 0, 0, ETH_ALEN, buf)) < 0) { | ||
1034 | dbg("Failed to read MAC address: %d", ret); | ||
1035 | goto out; | ||
1036 | } | ||
1037 | memcpy(dev->net->dev_addr, buf, ETH_ALEN); | ||
1038 | |||
1039 | /* Initialize MII structure */ | ||
1040 | dev->mii.dev = dev->net; | ||
1041 | dev->mii.mdio_read = asix_mdio_read; | ||
1042 | dev->mii.mdio_write = asix_mdio_write; | ||
1043 | dev->mii.phy_id_mask = 0x1f; | ||
1044 | dev->mii.reg_num_mask = 0x1f; | ||
1045 | dev->mii.phy_id = asix_get_phy_addr(dev); | ||
1046 | |||
1047 | phyid = asix_get_phyid(dev); | ||
1048 | dbg("PHYID=0x%08x", phyid); | ||
1049 | |||
1050 | if ((ret = asix_sw_reset(dev, AX_SWRESET_PRL)) < 0) | ||
1051 | goto out; | 1027 | goto out; |
1052 | 1028 | ||
1053 | msleep(150); | 1029 | msleep(150); |
1054 | 1030 | ||
1055 | if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL)) < 0) | 1031 | ret = asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL); |
1032 | if (ret < 0) | ||
1056 | goto out; | 1033 | goto out; |
1057 | 1034 | ||
1058 | msleep(150); | 1035 | msleep(150); |
1059 | 1036 | ||
1060 | dev->net->netdev_ops = &ax88772_netdev_ops; | ||
1061 | dev->net->ethtool_ops = &ax88772_ethtool_ops; | ||
1062 | |||
1063 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); | 1037 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); |
1064 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, | 1038 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, |
1065 | ADVERTISE_ALL | ADVERTISE_CSMA); | 1039 | ADVERTISE_ALL | ADVERTISE_CSMA); |
1066 | mii_nway_restart(&dev->mii); | 1040 | mii_nway_restart(&dev->mii); |
1067 | 1041 | ||
1068 | if ((ret = asix_write_medium_mode(dev, AX88772_MEDIUM_DEFAULT)) < 0) | 1042 | ret = asix_write_medium_mode(dev, AX88772_MEDIUM_DEFAULT); |
1043 | if (ret < 0) | ||
1069 | goto out; | 1044 | goto out; |
1070 | 1045 | ||
1071 | if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0, | 1046 | ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0, |
1072 | AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT, | 1047 | AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT, |
1073 | AX88772_IPG2_DEFAULT, 0, NULL)) < 0) { | 1048 | AX88772_IPG2_DEFAULT, 0, NULL); |
1049 | if (ret < 0) { | ||
1074 | dbg("Write IPG,IPG1,IPG2 failed: %d", ret); | 1050 | dbg("Write IPG,IPG1,IPG2 failed: %d", ret); |
1075 | goto out; | 1051 | goto out; |
1076 | } | 1052 | } |
1077 | 1053 | ||
1078 | /* Set RX_CTL to default values with 2k buffer, and enable cactus */ | 1054 | /* Set RX_CTL to default values with 2k buffer, and enable cactus */ |
1079 | if ((ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) < 0) | 1055 | ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL); |
1056 | if (ret < 0) | ||
1080 | goto out; | 1057 | goto out; |
1081 | 1058 | ||
1082 | rx_ctl = asix_read_rx_ctl(dev); | 1059 | rx_ctl = asix_read_rx_ctl(dev); |
@@ -1085,16 +1062,90 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) | |||
1085 | rx_ctl = asix_read_medium_status(dev); | 1062 | rx_ctl = asix_read_medium_status(dev); |
1086 | dbg("Medium Status is 0x%04x after all initializations", rx_ctl); | 1063 | dbg("Medium Status is 0x%04x after all initializations", rx_ctl); |
1087 | 1064 | ||
1065 | return 0; | ||
1066 | |||
1067 | out: | ||
1068 | return ret; | ||
1069 | |||
1070 | } | ||
1071 | |||
1072 | static const struct net_device_ops ax88772_netdev_ops = { | ||
1073 | .ndo_open = usbnet_open, | ||
1074 | .ndo_stop = usbnet_stop, | ||
1075 | .ndo_start_xmit = usbnet_start_xmit, | ||
1076 | .ndo_tx_timeout = usbnet_tx_timeout, | ||
1077 | .ndo_change_mtu = usbnet_change_mtu, | ||
1078 | .ndo_set_mac_address = asix_set_mac_address, | ||
1079 | .ndo_validate_addr = eth_validate_addr, | ||
1080 | .ndo_do_ioctl = asix_ioctl, | ||
1081 | .ndo_set_rx_mode = asix_set_multicast, | ||
1082 | }; | ||
1083 | |||
1084 | static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) | ||
1085 | { | ||
1086 | int ret, embd_phy; | ||
1087 | struct asix_data *data = (struct asix_data *)&dev->data; | ||
1088 | u8 buf[ETH_ALEN]; | ||
1089 | u32 phyid; | ||
1090 | |||
1091 | data->eeprom_len = AX88772_EEPROM_LEN; | ||
1092 | |||
1093 | usbnet_get_endpoints(dev,intf); | ||
1094 | |||
1095 | /* Get the MAC address */ | ||
1096 | ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf); | ||
1097 | if (ret < 0) { | ||
1098 | dbg("Failed to read MAC address: %d", ret); | ||
1099 | return ret; | ||
1100 | } | ||
1101 | memcpy(dev->net->dev_addr, buf, ETH_ALEN); | ||
1102 | |||
1103 | /* Initialize MII structure */ | ||
1104 | dev->mii.dev = dev->net; | ||
1105 | dev->mii.mdio_read = asix_mdio_read; | ||
1106 | dev->mii.mdio_write = asix_mdio_write; | ||
1107 | dev->mii.phy_id_mask = 0x1f; | ||
1108 | dev->mii.reg_num_mask = 0x1f; | ||
1109 | dev->mii.phy_id = asix_get_phy_addr(dev); | ||
1110 | |||
1111 | dev->net->netdev_ops = &ax88772_netdev_ops; | ||
1112 | dev->net->ethtool_ops = &ax88772_ethtool_ops; | ||
1113 | |||
1114 | embd_phy = ((dev->mii.phy_id & 0x1f) == 0x10 ? 1 : 0); | ||
1115 | |||
1116 | /* Reset the PHY to normal operation mode */ | ||
1117 | ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL); | ||
1118 | if (ret < 0) { | ||
1119 | dbg("Select PHY #1 failed: %d", ret); | ||
1120 | return ret; | ||
1121 | } | ||
1122 | |||
1123 | ret = asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL); | ||
1124 | if (ret < 0) | ||
1125 | return ret; | ||
1126 | |||
1127 | msleep(150); | ||
1128 | |||
1129 | ret = asix_sw_reset(dev, AX_SWRESET_CLEAR); | ||
1130 | if (ret < 0) | ||
1131 | return ret; | ||
1132 | |||
1133 | msleep(150); | ||
1134 | |||
1135 | ret = asix_sw_reset(dev, embd_phy ? AX_SWRESET_IPRL : AX_SWRESET_PRTE); | ||
1136 | |||
1137 | /* Read PHYID register *AFTER* the PHY was reset properly */ | ||
1138 | phyid = asix_get_phyid(dev); | ||
1139 | dbg("PHYID=0x%08x", phyid); | ||
1140 | |||
1088 | /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */ | 1141 | /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */ |
1089 | if (dev->driver_info->flags & FLAG_FRAMING_AX) { | 1142 | if (dev->driver_info->flags & FLAG_FRAMING_AX) { |
1090 | /* hard_mtu is still the default - the device does not support | 1143 | /* hard_mtu is still the default - the device does not support |
1091 | jumbo eth frames */ | 1144 | jumbo eth frames */ |
1092 | dev->rx_urb_size = 2048; | 1145 | dev->rx_urb_size = 2048; |
1093 | } | 1146 | } |
1094 | return 0; | ||
1095 | 1147 | ||
1096 | out: | 1148 | return 0; |
1097 | return ret; | ||
1098 | } | 1149 | } |
1099 | 1150 | ||
1100 | static struct ethtool_ops ax88178_ethtool_ops = { | 1151 | static struct ethtool_ops ax88178_ethtool_ops = { |
@@ -1143,6 +1194,27 @@ static int marvell_phy_init(struct usbnet *dev) | |||
1143 | return 0; | 1194 | return 0; |
1144 | } | 1195 | } |
1145 | 1196 | ||
1197 | static int rtl8211cl_phy_init(struct usbnet *dev) | ||
1198 | { | ||
1199 | struct asix_data *data = (struct asix_data *)&dev->data; | ||
1200 | |||
1201 | netdev_dbg(dev->net, "rtl8211cl_phy_init()\n"); | ||
1202 | |||
1203 | asix_mdio_write (dev->net, dev->mii.phy_id, 0x1f, 0x0005); | ||
1204 | asix_mdio_write (dev->net, dev->mii.phy_id, 0x0c, 0); | ||
1205 | asix_mdio_write (dev->net, dev->mii.phy_id, 0x01, | ||
1206 | asix_mdio_read (dev->net, dev->mii.phy_id, 0x01) | 0x0080); | ||
1207 | asix_mdio_write (dev->net, dev->mii.phy_id, 0x1f, 0); | ||
1208 | |||
1209 | if (data->ledmode == 12) { | ||
1210 | asix_mdio_write (dev->net, dev->mii.phy_id, 0x1f, 0x0002); | ||
1211 | asix_mdio_write (dev->net, dev->mii.phy_id, 0x1a, 0x00cb); | ||
1212 | asix_mdio_write (dev->net, dev->mii.phy_id, 0x1f, 0); | ||
1213 | } | ||
1214 | |||
1215 | return 0; | ||
1216 | } | ||
1217 | |||
1146 | static int marvell_led_status(struct usbnet *dev, u16 speed) | 1218 | static int marvell_led_status(struct usbnet *dev, u16 speed) |
1147 | { | 1219 | { |
1148 | u16 reg = asix_mdio_read(dev->net, dev->mii.phy_id, MARVELL_LED_MANUAL); | 1220 | u16 reg = asix_mdio_read(dev->net, dev->mii.phy_id, MARVELL_LED_MANUAL); |
@@ -1169,6 +1241,88 @@ static int marvell_led_status(struct usbnet *dev, u16 speed) | |||
1169 | return 0; | 1241 | return 0; |
1170 | } | 1242 | } |
1171 | 1243 | ||
1244 | static int ax88178_reset(struct usbnet *dev) | ||
1245 | { | ||
1246 | struct asix_data *data = (struct asix_data *)&dev->data; | ||
1247 | int ret; | ||
1248 | __le16 eeprom; | ||
1249 | u8 status; | ||
1250 | int gpio0 = 0; | ||
1251 | u32 phyid; | ||
1252 | |||
1253 | asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &status); | ||
1254 | dbg("GPIO Status: 0x%04x", status); | ||
1255 | |||
1256 | asix_write_cmd(dev, AX_CMD_WRITE_ENABLE, 0, 0, 0, NULL); | ||
1257 | asix_read_cmd(dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2, &eeprom); | ||
1258 | asix_write_cmd(dev, AX_CMD_WRITE_DISABLE, 0, 0, 0, NULL); | ||
1259 | |||
1260 | dbg("EEPROM index 0x17 is 0x%04x", eeprom); | ||
1261 | |||
1262 | if (eeprom == cpu_to_le16(0xffff)) { | ||
1263 | data->phymode = PHY_MODE_MARVELL; | ||
1264 | data->ledmode = 0; | ||
1265 | gpio0 = 1; | ||
1266 | } else { | ||
1267 | data->phymode = le16_to_cpu(eeprom) & 0x7F; | ||
1268 | data->ledmode = le16_to_cpu(eeprom) >> 8; | ||
1269 | gpio0 = (le16_to_cpu(eeprom) & 0x80) ? 0 : 1; | ||
1270 | } | ||
1271 | dbg("GPIO0: %d, PhyMode: %d", gpio0, data->phymode); | ||
1272 | |||
1273 | /* Power up external GigaPHY through AX88178 GPIO pin */ | ||
1274 | asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_1 | AX_GPIO_GPO1EN, 40); | ||
1275 | if ((le16_to_cpu(eeprom) >> 8) != 1) { | ||
1276 | asix_write_gpio(dev, 0x003c, 30); | ||
1277 | asix_write_gpio(dev, 0x001c, 300); | ||
1278 | asix_write_gpio(dev, 0x003c, 30); | ||
1279 | } else { | ||
1280 | dbg("gpio phymode == 1 path"); | ||
1281 | asix_write_gpio(dev, AX_GPIO_GPO1EN, 30); | ||
1282 | asix_write_gpio(dev, AX_GPIO_GPO1EN | AX_GPIO_GPO_1, 30); | ||
1283 | } | ||
1284 | |||
1285 | /* Read PHYID register *AFTER* powering up PHY */ | ||
1286 | phyid = asix_get_phyid(dev); | ||
1287 | dbg("PHYID=0x%08x", phyid); | ||
1288 | |||
1289 | /* Set AX88178 to enable MII/GMII/RGMII interface for external PHY */ | ||
1290 | asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, 0, 0, 0, NULL); | ||
1291 | |||
1292 | asix_sw_reset(dev, 0); | ||
1293 | msleep(150); | ||
1294 | |||
1295 | asix_sw_reset(dev, AX_SWRESET_PRL | AX_SWRESET_IPPD); | ||
1296 | msleep(150); | ||
1297 | |||
1298 | asix_write_rx_ctl(dev, 0); | ||
1299 | |||
1300 | if (data->phymode == PHY_MODE_MARVELL) { | ||
1301 | marvell_phy_init(dev); | ||
1302 | msleep(60); | ||
1303 | } else if (data->phymode == PHY_MODE_RTL8211CL) | ||
1304 | rtl8211cl_phy_init(dev); | ||
1305 | |||
1306 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, | ||
1307 | BMCR_RESET | BMCR_ANENABLE); | ||
1308 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, | ||
1309 | ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); | ||
1310 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_CTRL1000, | ||
1311 | ADVERTISE_1000FULL); | ||
1312 | |||
1313 | mii_nway_restart(&dev->mii); | ||
1314 | |||
1315 | ret = asix_write_medium_mode(dev, AX88178_MEDIUM_DEFAULT); | ||
1316 | if (ret < 0) | ||
1317 | return ret; | ||
1318 | |||
1319 | ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL); | ||
1320 | if (ret < 0) | ||
1321 | return ret; | ||
1322 | |||
1323 | return 0; | ||
1324 | } | ||
1325 | |||
1172 | static int ax88178_link_reset(struct usbnet *dev) | 1326 | static int ax88178_link_reset(struct usbnet *dev) |
1173 | { | 1327 | { |
1174 | u16 mode; | 1328 | u16 mode; |
@@ -1270,67 +1424,26 @@ static const struct net_device_ops ax88178_netdev_ops = { | |||
1270 | .ndo_tx_timeout = usbnet_tx_timeout, | 1424 | .ndo_tx_timeout = usbnet_tx_timeout, |
1271 | .ndo_set_mac_address = asix_set_mac_address, | 1425 | .ndo_set_mac_address = asix_set_mac_address, |
1272 | .ndo_validate_addr = eth_validate_addr, | 1426 | .ndo_validate_addr = eth_validate_addr, |
1273 | .ndo_set_multicast_list = asix_set_multicast, | 1427 | .ndo_set_rx_mode = asix_set_multicast, |
1274 | .ndo_do_ioctl = asix_ioctl, | 1428 | .ndo_do_ioctl = asix_ioctl, |
1275 | .ndo_change_mtu = ax88178_change_mtu, | 1429 | .ndo_change_mtu = ax88178_change_mtu, |
1276 | }; | 1430 | }; |
1277 | 1431 | ||
1278 | static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) | 1432 | static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) |
1279 | { | 1433 | { |
1280 | struct asix_data *data = (struct asix_data *)&dev->data; | ||
1281 | int ret; | 1434 | int ret; |
1282 | u8 buf[ETH_ALEN]; | 1435 | u8 buf[ETH_ALEN]; |
1283 | __le16 eeprom; | 1436 | struct asix_data *data = (struct asix_data *)&dev->data; |
1284 | u8 status; | ||
1285 | int gpio0 = 0; | ||
1286 | u32 phyid; | ||
1287 | |||
1288 | usbnet_get_endpoints(dev,intf); | ||
1289 | |||
1290 | asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &status); | ||
1291 | dbg("GPIO Status: 0x%04x", status); | ||
1292 | |||
1293 | asix_write_cmd(dev, AX_CMD_WRITE_ENABLE, 0, 0, 0, NULL); | ||
1294 | asix_read_cmd(dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2, &eeprom); | ||
1295 | asix_write_cmd(dev, AX_CMD_WRITE_DISABLE, 0, 0, 0, NULL); | ||
1296 | |||
1297 | dbg("EEPROM index 0x17 is 0x%04x", eeprom); | ||
1298 | |||
1299 | if (eeprom == cpu_to_le16(0xffff)) { | ||
1300 | data->phymode = PHY_MODE_MARVELL; | ||
1301 | data->ledmode = 0; | ||
1302 | gpio0 = 1; | ||
1303 | } else { | ||
1304 | data->phymode = le16_to_cpu(eeprom) & 7; | ||
1305 | data->ledmode = le16_to_cpu(eeprom) >> 8; | ||
1306 | gpio0 = (le16_to_cpu(eeprom) & 0x80) ? 0 : 1; | ||
1307 | } | ||
1308 | dbg("GPIO0: %d, PhyMode: %d", gpio0, data->phymode); | ||
1309 | |||
1310 | asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_1 | AX_GPIO_GPO1EN, 40); | ||
1311 | if ((le16_to_cpu(eeprom) >> 8) != 1) { | ||
1312 | asix_write_gpio(dev, 0x003c, 30); | ||
1313 | asix_write_gpio(dev, 0x001c, 300); | ||
1314 | asix_write_gpio(dev, 0x003c, 30); | ||
1315 | } else { | ||
1316 | dbg("gpio phymode == 1 path"); | ||
1317 | asix_write_gpio(dev, AX_GPIO_GPO1EN, 30); | ||
1318 | asix_write_gpio(dev, AX_GPIO_GPO1EN | AX_GPIO_GPO_1, 30); | ||
1319 | } | ||
1320 | |||
1321 | asix_sw_reset(dev, 0); | ||
1322 | msleep(150); | ||
1323 | 1437 | ||
1324 | asix_sw_reset(dev, AX_SWRESET_PRL | AX_SWRESET_IPPD); | 1438 | data->eeprom_len = AX88772_EEPROM_LEN; |
1325 | msleep(150); | ||
1326 | 1439 | ||
1327 | asix_write_rx_ctl(dev, 0); | 1440 | usbnet_get_endpoints(dev,intf); |
1328 | 1441 | ||
1329 | /* Get the MAC address */ | 1442 | /* Get the MAC address */ |
1330 | if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, | 1443 | ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf); |
1331 | 0, 0, ETH_ALEN, buf)) < 0) { | 1444 | if (ret < 0) { |
1332 | dbg("Failed to read MAC address: %d", ret); | 1445 | dbg("Failed to read MAC address: %d", ret); |
1333 | goto out; | 1446 | return ret; |
1334 | } | 1447 | } |
1335 | memcpy(dev->net->dev_addr, buf, ETH_ALEN); | 1448 | memcpy(dev->net->dev_addr, buf, ETH_ALEN); |
1336 | 1449 | ||
@@ -1346,28 +1459,12 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) | |||
1346 | dev->net->netdev_ops = &ax88178_netdev_ops; | 1459 | dev->net->netdev_ops = &ax88178_netdev_ops; |
1347 | dev->net->ethtool_ops = &ax88178_ethtool_ops; | 1460 | dev->net->ethtool_ops = &ax88178_ethtool_ops; |
1348 | 1461 | ||
1349 | phyid = asix_get_phyid(dev); | 1462 | /* Blink LEDS so users know driver saw dongle */ |
1350 | dbg("PHYID=0x%08x", phyid); | 1463 | asix_sw_reset(dev, 0); |
1351 | 1464 | msleep(150); | |
1352 | if (data->phymode == PHY_MODE_MARVELL) { | ||
1353 | marvell_phy_init(dev); | ||
1354 | msleep(60); | ||
1355 | } | ||
1356 | |||
1357 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, | ||
1358 | BMCR_RESET | BMCR_ANENABLE); | ||
1359 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, | ||
1360 | ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); | ||
1361 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_CTRL1000, | ||
1362 | ADVERTISE_1000FULL); | ||
1363 | |||
1364 | mii_nway_restart(&dev->mii); | ||
1365 | |||
1366 | if ((ret = asix_write_medium_mode(dev, AX88178_MEDIUM_DEFAULT)) < 0) | ||
1367 | goto out; | ||
1368 | 1465 | ||
1369 | if ((ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) < 0) | 1466 | asix_sw_reset(dev, AX_SWRESET_PRL | AX_SWRESET_IPPD); |
1370 | goto out; | 1467 | msleep(150); |
1371 | 1468 | ||
1372 | /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */ | 1469 | /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */ |
1373 | if (dev->driver_info->flags & FLAG_FRAMING_AX) { | 1470 | if (dev->driver_info->flags & FLAG_FRAMING_AX) { |
@@ -1375,10 +1472,8 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) | |||
1375 | jumbo eth frames */ | 1472 | jumbo eth frames */ |
1376 | dev->rx_urb_size = 2048; | 1473 | dev->rx_urb_size = 2048; |
1377 | } | 1474 | } |
1378 | return 0; | ||
1379 | 1475 | ||
1380 | out: | 1476 | return 0; |
1381 | return ret; | ||
1382 | } | 1477 | } |
1383 | 1478 | ||
1384 | static const struct driver_info ax8817x_info = { | 1479 | static const struct driver_info ax8817x_info = { |
@@ -1426,7 +1521,7 @@ static const struct driver_info ax88772_info = { | |||
1426 | .bind = ax88772_bind, | 1521 | .bind = ax88772_bind, |
1427 | .status = asix_status, | 1522 | .status = asix_status, |
1428 | .link_reset = ax88772_link_reset, | 1523 | .link_reset = ax88772_link_reset, |
1429 | .reset = ax88772_link_reset, | 1524 | .reset = ax88772_reset, |
1430 | .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR, | 1525 | .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR, |
1431 | .rx_fixup = asix_rx_fixup, | 1526 | .rx_fixup = asix_rx_fixup, |
1432 | .tx_fixup = asix_tx_fixup, | 1527 | .tx_fixup = asix_tx_fixup, |
@@ -1437,7 +1532,7 @@ static const struct driver_info ax88178_info = { | |||
1437 | .bind = ax88178_bind, | 1532 | .bind = ax88178_bind, |
1438 | .status = asix_status, | 1533 | .status = asix_status, |
1439 | .link_reset = ax88178_link_reset, | 1534 | .link_reset = ax88178_link_reset, |
1440 | .reset = ax88178_link_reset, | 1535 | .reset = ax88178_reset, |
1441 | .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR, | 1536 | .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR, |
1442 | .rx_fixup = asix_rx_fixup, | 1537 | .rx_fixup = asix_rx_fixup, |
1443 | .tx_fixup = asix_tx_fixup, | 1538 | .tx_fixup = asix_tx_fixup, |
@@ -1566,7 +1661,7 @@ static const struct usb_device_id products [] = { | |||
1566 | MODULE_DEVICE_TABLE(usb, products); | 1661 | MODULE_DEVICE_TABLE(usb, products); |
1567 | 1662 | ||
1568 | static struct usb_driver asix_driver = { | 1663 | static struct usb_driver asix_driver = { |
1569 | .name = "asix", | 1664 | .name = DRIVER_NAME, |
1570 | .id_table = products, | 1665 | .id_table = products, |
1571 | .probe = usbnet_probe, | 1666 | .probe = usbnet_probe, |
1572 | .suspend = usbnet_suspend, | 1667 | .suspend = usbnet_suspend, |
@@ -1588,6 +1683,7 @@ static void __exit asix_exit(void) | |||
1588 | module_exit(asix_exit); | 1683 | module_exit(asix_exit); |
1589 | 1684 | ||
1590 | MODULE_AUTHOR("David Hollis"); | 1685 | MODULE_AUTHOR("David Hollis"); |
1686 | MODULE_VERSION(DRIVER_VERSION); | ||
1591 | MODULE_DESCRIPTION("ASIX AX8817X based USB 2.0 Ethernet Devices"); | 1687 | MODULE_DESCRIPTION("ASIX AX8817X based USB 2.0 Ethernet Devices"); |
1592 | MODULE_LICENSE("GPL"); | 1688 | MODULE_LICENSE("GPL"); |
1593 | 1689 | ||