diff options
Diffstat (limited to 'drivers/net/usb/asix.c')
-rw-r--r-- | drivers/net/usb/asix.c | 68 |
1 files changed, 52 insertions, 16 deletions
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index e81e22e3d1d2..e6fed4d4cb77 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c | |||
@@ -36,7 +36,7 @@ | |||
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 "26-Sep-2011" | 39 | #define DRIVER_VERSION "08-Nov-2011" |
40 | #define 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 */ |
@@ -163,7 +163,7 @@ | |||
163 | #define MARVELL_CTRL_TXDELAY 0x0002 | 163 | #define MARVELL_CTRL_TXDELAY 0x0002 |
164 | #define MARVELL_CTRL_RXDELAY 0x0080 | 164 | #define MARVELL_CTRL_RXDELAY 0x0080 |
165 | 165 | ||
166 | #define PHY_MODE_RTL8211CL 0x0004 | 166 | #define PHY_MODE_RTL8211CL 0x000C |
167 | 167 | ||
168 | /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ | 168 | /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ |
169 | struct asix_data { | 169 | struct asix_data { |
@@ -652,9 +652,17 @@ static u32 asix_get_phyid(struct usbnet *dev) | |||
652 | { | 652 | { |
653 | int phy_reg; | 653 | int phy_reg; |
654 | u32 phy_id; | 654 | u32 phy_id; |
655 | int i; | ||
655 | 656 | ||
656 | 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. */ |
657 | 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) | ||
658 | return 0; | 666 | return 0; |
659 | 667 | ||
660 | phy_id = (phy_reg & 0xffff) << 16; | 668 | phy_id = (phy_reg & 0xffff) << 16; |
@@ -1075,7 +1083,7 @@ static const struct net_device_ops ax88772_netdev_ops = { | |||
1075 | 1083 | ||
1076 | static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) | 1084 | static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) |
1077 | { | 1085 | { |
1078 | int ret; | 1086 | int ret, embd_phy; |
1079 | struct asix_data *data = (struct asix_data *)&dev->data; | 1087 | struct asix_data *data = (struct asix_data *)&dev->data; |
1080 | u8 buf[ETH_ALEN]; | 1088 | u8 buf[ETH_ALEN]; |
1081 | u32 phyid; | 1089 | u32 phyid; |
@@ -1100,16 +1108,36 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) | |||
1100 | dev->mii.reg_num_mask = 0x1f; | 1108 | dev->mii.reg_num_mask = 0x1f; |
1101 | dev->mii.phy_id = asix_get_phy_addr(dev); | 1109 | dev->mii.phy_id = asix_get_phy_addr(dev); |
1102 | 1110 | ||
1103 | phyid = asix_get_phyid(dev); | ||
1104 | dbg("PHYID=0x%08x", phyid); | ||
1105 | |||
1106 | dev->net->netdev_ops = &ax88772_netdev_ops; | 1111 | dev->net->netdev_ops = &ax88772_netdev_ops; |
1107 | dev->net->ethtool_ops = &ax88772_ethtool_ops; | 1112 | dev->net->ethtool_ops = &ax88772_ethtool_ops; |
1108 | 1113 | ||
1109 | ret = ax88772_reset(dev); | 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); | ||
1110 | if (ret < 0) | 1130 | if (ret < 0) |
1111 | return ret; | 1131 | return ret; |
1112 | 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 | |||
1113 | /* 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 */ |
1114 | if (dev->driver_info->flags & FLAG_FRAMING_AX) { | 1142 | if (dev->driver_info->flags & FLAG_FRAMING_AX) { |
1115 | /* hard_mtu is still the default - the device does not support | 1143 | /* hard_mtu is still the default - the device does not support |
@@ -1220,6 +1248,7 @@ static int ax88178_reset(struct usbnet *dev) | |||
1220 | __le16 eeprom; | 1248 | __le16 eeprom; |
1221 | u8 status; | 1249 | u8 status; |
1222 | int gpio0 = 0; | 1250 | int gpio0 = 0; |
1251 | u32 phyid; | ||
1223 | 1252 | ||
1224 | asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &status); | 1253 | asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &status); |
1225 | dbg("GPIO Status: 0x%04x", status); | 1254 | dbg("GPIO Status: 0x%04x", status); |
@@ -1235,12 +1264,13 @@ static int ax88178_reset(struct usbnet *dev) | |||
1235 | data->ledmode = 0; | 1264 | data->ledmode = 0; |
1236 | gpio0 = 1; | 1265 | gpio0 = 1; |
1237 | } else { | 1266 | } else { |
1238 | data->phymode = le16_to_cpu(eeprom) & 7; | 1267 | data->phymode = le16_to_cpu(eeprom) & 0x7F; |
1239 | data->ledmode = le16_to_cpu(eeprom) >> 8; | 1268 | data->ledmode = le16_to_cpu(eeprom) >> 8; |
1240 | gpio0 = (le16_to_cpu(eeprom) & 0x80) ? 0 : 1; | 1269 | gpio0 = (le16_to_cpu(eeprom) & 0x80) ? 0 : 1; |
1241 | } | 1270 | } |
1242 | dbg("GPIO0: %d, PhyMode: %d", gpio0, data->phymode); | 1271 | dbg("GPIO0: %d, PhyMode: %d", gpio0, data->phymode); |
1243 | 1272 | ||
1273 | /* Power up external GigaPHY through AX88178 GPIO pin */ | ||
1244 | asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_1 | AX_GPIO_GPO1EN, 40); | 1274 | asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_1 | AX_GPIO_GPO1EN, 40); |
1245 | if ((le16_to_cpu(eeprom) >> 8) != 1) { | 1275 | if ((le16_to_cpu(eeprom) >> 8) != 1) { |
1246 | asix_write_gpio(dev, 0x003c, 30); | 1276 | asix_write_gpio(dev, 0x003c, 30); |
@@ -1252,6 +1282,13 @@ static int ax88178_reset(struct usbnet *dev) | |||
1252 | asix_write_gpio(dev, AX_GPIO_GPO1EN | AX_GPIO_GPO_1, 30); | 1282 | asix_write_gpio(dev, AX_GPIO_GPO1EN | AX_GPIO_GPO_1, 30); |
1253 | } | 1283 | } |
1254 | 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 | |||
1255 | asix_sw_reset(dev, 0); | 1292 | asix_sw_reset(dev, 0); |
1256 | msleep(150); | 1293 | msleep(150); |
1257 | 1294 | ||
@@ -1396,7 +1433,6 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) | |||
1396 | { | 1433 | { |
1397 | int ret; | 1434 | int ret; |
1398 | u8 buf[ETH_ALEN]; | 1435 | u8 buf[ETH_ALEN]; |
1399 | u32 phyid; | ||
1400 | struct asix_data *data = (struct asix_data *)&dev->data; | 1436 | struct asix_data *data = (struct asix_data *)&dev->data; |
1401 | 1437 | ||
1402 | data->eeprom_len = AX88772_EEPROM_LEN; | 1438 | data->eeprom_len = AX88772_EEPROM_LEN; |
@@ -1423,12 +1459,12 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) | |||
1423 | dev->net->netdev_ops = &ax88178_netdev_ops; | 1459 | dev->net->netdev_ops = &ax88178_netdev_ops; |
1424 | dev->net->ethtool_ops = &ax88178_ethtool_ops; | 1460 | dev->net->ethtool_ops = &ax88178_ethtool_ops; |
1425 | 1461 | ||
1426 | phyid = asix_get_phyid(dev); | 1462 | /* Blink LEDS so users know driver saw dongle */ |
1427 | dbg("PHYID=0x%08x", phyid); | 1463 | asix_sw_reset(dev, 0); |
1464 | msleep(150); | ||
1428 | 1465 | ||
1429 | ret = ax88178_reset(dev); | 1466 | asix_sw_reset(dev, AX_SWRESET_PRL | AX_SWRESET_IPPD); |
1430 | if (ret < 0) | 1467 | msleep(150); |
1431 | return ret; | ||
1432 | 1468 | ||
1433 | /* 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 */ |
1434 | if (dev->driver_info->flags & FLAG_FRAMING_AX) { | 1470 | if (dev->driver_info->flags & FLAG_FRAMING_AX) { |