diff options
Diffstat (limited to 'drivers/net/usb/asix.c')
-rw-r--r-- | drivers/net/usb/asix.c | 163 |
1 files changed, 101 insertions, 62 deletions
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 9e0b3776b80a..8d48affb65fd 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c | |||
@@ -164,6 +164,8 @@ static const char driver_name [] = "asix"; | |||
164 | #define MARVELL_CTRL_TXDELAY 0x0002 | 164 | #define MARVELL_CTRL_TXDELAY 0x0002 |
165 | #define MARVELL_CTRL_RXDELAY 0x0080 | 165 | #define MARVELL_CTRL_RXDELAY 0x0080 |
166 | 166 | ||
167 | #define PHY_MODE_RTL8211CL 0x0004 | ||
168 | |||
167 | /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ | 169 | /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ |
168 | struct asix_data { | 170 | struct asix_data { |
169 | u8 multi_filter[AX_MCAST_FILTER_SIZE]; | 171 | u8 multi_filter[AX_MCAST_FILTER_SIZE]; |
@@ -1149,6 +1151,27 @@ static int marvell_phy_init(struct usbnet *dev) | |||
1149 | return 0; | 1151 | return 0; |
1150 | } | 1152 | } |
1151 | 1153 | ||
1154 | static int rtl8211cl_phy_init(struct usbnet *dev) | ||
1155 | { | ||
1156 | struct asix_data *data = (struct asix_data *)&dev->data; | ||
1157 | |||
1158 | netdev_dbg(dev->net, "rtl8211cl_phy_init()\n"); | ||
1159 | |||
1160 | asix_mdio_write (dev->net, dev->mii.phy_id, 0x1f, 0x0005); | ||
1161 | asix_mdio_write (dev->net, dev->mii.phy_id, 0x0c, 0); | ||
1162 | asix_mdio_write (dev->net, dev->mii.phy_id, 0x01, | ||
1163 | asix_mdio_read (dev->net, dev->mii.phy_id, 0x01) | 0x0080); | ||
1164 | asix_mdio_write (dev->net, dev->mii.phy_id, 0x1f, 0); | ||
1165 | |||
1166 | if (data->ledmode == 12) { | ||
1167 | asix_mdio_write (dev->net, dev->mii.phy_id, 0x1f, 0x0002); | ||
1168 | asix_mdio_write (dev->net, dev->mii.phy_id, 0x1a, 0x00cb); | ||
1169 | asix_mdio_write (dev->net, dev->mii.phy_id, 0x1f, 0); | ||
1170 | } | ||
1171 | |||
1172 | return 0; | ||
1173 | } | ||
1174 | |||
1152 | static int marvell_led_status(struct usbnet *dev, u16 speed) | 1175 | static int marvell_led_status(struct usbnet *dev, u16 speed) |
1153 | { | 1176 | { |
1154 | u16 reg = asix_mdio_read(dev->net, dev->mii.phy_id, MARVELL_LED_MANUAL); | 1177 | u16 reg = asix_mdio_read(dev->net, dev->mii.phy_id, MARVELL_LED_MANUAL); |
@@ -1175,6 +1198,81 @@ static int marvell_led_status(struct usbnet *dev, u16 speed) | |||
1175 | return 0; | 1198 | return 0; |
1176 | } | 1199 | } |
1177 | 1200 | ||
1201 | static int ax88178_reset(struct usbnet *dev) | ||
1202 | { | ||
1203 | struct asix_data *data = (struct asix_data *)&dev->data; | ||
1204 | int ret; | ||
1205 | __le16 eeprom; | ||
1206 | u8 status; | ||
1207 | int gpio0 = 0; | ||
1208 | |||
1209 | asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &status); | ||
1210 | dbg("GPIO Status: 0x%04x", status); | ||
1211 | |||
1212 | asix_write_cmd(dev, AX_CMD_WRITE_ENABLE, 0, 0, 0, NULL); | ||
1213 | asix_read_cmd(dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2, &eeprom); | ||
1214 | asix_write_cmd(dev, AX_CMD_WRITE_DISABLE, 0, 0, 0, NULL); | ||
1215 | |||
1216 | dbg("EEPROM index 0x17 is 0x%04x", eeprom); | ||
1217 | |||
1218 | if (eeprom == cpu_to_le16(0xffff)) { | ||
1219 | data->phymode = PHY_MODE_MARVELL; | ||
1220 | data->ledmode = 0; | ||
1221 | gpio0 = 1; | ||
1222 | } else { | ||
1223 | data->phymode = le16_to_cpu(eeprom) & 7; | ||
1224 | data->ledmode = le16_to_cpu(eeprom) >> 8; | ||
1225 | gpio0 = (le16_to_cpu(eeprom) & 0x80) ? 0 : 1; | ||
1226 | } | ||
1227 | dbg("GPIO0: %d, PhyMode: %d", gpio0, data->phymode); | ||
1228 | |||
1229 | asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_1 | AX_GPIO_GPO1EN, 40); | ||
1230 | if ((le16_to_cpu(eeprom) >> 8) != 1) { | ||
1231 | asix_write_gpio(dev, 0x003c, 30); | ||
1232 | asix_write_gpio(dev, 0x001c, 300); | ||
1233 | asix_write_gpio(dev, 0x003c, 30); | ||
1234 | } else { | ||
1235 | dbg("gpio phymode == 1 path"); | ||
1236 | asix_write_gpio(dev, AX_GPIO_GPO1EN, 30); | ||
1237 | asix_write_gpio(dev, AX_GPIO_GPO1EN | AX_GPIO_GPO_1, 30); | ||
1238 | } | ||
1239 | |||
1240 | asix_sw_reset(dev, 0); | ||
1241 | msleep(150); | ||
1242 | |||
1243 | asix_sw_reset(dev, AX_SWRESET_PRL | AX_SWRESET_IPPD); | ||
1244 | msleep(150); | ||
1245 | |||
1246 | asix_write_rx_ctl(dev, 0); | ||
1247 | |||
1248 | if (data->phymode == PHY_MODE_MARVELL) { | ||
1249 | marvell_phy_init(dev); | ||
1250 | msleep(60); | ||
1251 | } else if (data->phymode == PHY_MODE_RTL8211CL) | ||
1252 | rtl8211cl_phy_init(dev); | ||
1253 | |||
1254 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, | ||
1255 | BMCR_RESET | BMCR_ANENABLE); | ||
1256 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, | ||
1257 | ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); | ||
1258 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_CTRL1000, | ||
1259 | ADVERTISE_1000FULL); | ||
1260 | |||
1261 | mii_nway_restart(&dev->mii); | ||
1262 | |||
1263 | if ((ret = asix_write_medium_mode(dev, AX88178_MEDIUM_DEFAULT)) < 0) | ||
1264 | goto out; | ||
1265 | |||
1266 | if ((ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) < 0) | ||
1267 | goto out; | ||
1268 | |||
1269 | return 0; | ||
1270 | |||
1271 | out: | ||
1272 | return ret; | ||
1273 | |||
1274 | } | ||
1275 | |||
1178 | static int ax88178_link_reset(struct usbnet *dev) | 1276 | static int ax88178_link_reset(struct usbnet *dev) |
1179 | { | 1277 | { |
1180 | u16 mode; | 1278 | u16 mode; |
@@ -1283,55 +1381,12 @@ static const struct net_device_ops ax88178_netdev_ops = { | |||
1283 | 1381 | ||
1284 | static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) | 1382 | static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) |
1285 | { | 1383 | { |
1286 | struct asix_data *data = (struct asix_data *)&dev->data; | ||
1287 | int ret; | 1384 | int ret; |
1288 | u8 buf[ETH_ALEN]; | 1385 | u8 buf[ETH_ALEN]; |
1289 | __le16 eeprom; | ||
1290 | u8 status; | ||
1291 | int gpio0 = 0; | ||
1292 | u32 phyid; | 1386 | u32 phyid; |
1293 | 1387 | ||
1294 | usbnet_get_endpoints(dev,intf); | 1388 | usbnet_get_endpoints(dev,intf); |
1295 | 1389 | ||
1296 | asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &status); | ||
1297 | dbg("GPIO Status: 0x%04x", status); | ||
1298 | |||
1299 | asix_write_cmd(dev, AX_CMD_WRITE_ENABLE, 0, 0, 0, NULL); | ||
1300 | asix_read_cmd(dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2, &eeprom); | ||
1301 | asix_write_cmd(dev, AX_CMD_WRITE_DISABLE, 0, 0, 0, NULL); | ||
1302 | |||
1303 | dbg("EEPROM index 0x17 is 0x%04x", eeprom); | ||
1304 | |||
1305 | if (eeprom == cpu_to_le16(0xffff)) { | ||
1306 | data->phymode = PHY_MODE_MARVELL; | ||
1307 | data->ledmode = 0; | ||
1308 | gpio0 = 1; | ||
1309 | } else { | ||
1310 | data->phymode = le16_to_cpu(eeprom) & 7; | ||
1311 | data->ledmode = le16_to_cpu(eeprom) >> 8; | ||
1312 | gpio0 = (le16_to_cpu(eeprom) & 0x80) ? 0 : 1; | ||
1313 | } | ||
1314 | dbg("GPIO0: %d, PhyMode: %d", gpio0, data->phymode); | ||
1315 | |||
1316 | asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_1 | AX_GPIO_GPO1EN, 40); | ||
1317 | if ((le16_to_cpu(eeprom) >> 8) != 1) { | ||
1318 | asix_write_gpio(dev, 0x003c, 30); | ||
1319 | asix_write_gpio(dev, 0x001c, 300); | ||
1320 | asix_write_gpio(dev, 0x003c, 30); | ||
1321 | } else { | ||
1322 | dbg("gpio phymode == 1 path"); | ||
1323 | asix_write_gpio(dev, AX_GPIO_GPO1EN, 30); | ||
1324 | asix_write_gpio(dev, AX_GPIO_GPO1EN | AX_GPIO_GPO_1, 30); | ||
1325 | } | ||
1326 | |||
1327 | asix_sw_reset(dev, 0); | ||
1328 | msleep(150); | ||
1329 | |||
1330 | asix_sw_reset(dev, AX_SWRESET_PRL | AX_SWRESET_IPPD); | ||
1331 | msleep(150); | ||
1332 | |||
1333 | asix_write_rx_ctl(dev, 0); | ||
1334 | |||
1335 | /* Get the MAC address */ | 1390 | /* Get the MAC address */ |
1336 | if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, | 1391 | if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, |
1337 | 0, 0, ETH_ALEN, buf)) < 0) { | 1392 | 0, 0, ETH_ALEN, buf)) < 0) { |
@@ -1355,24 +1410,8 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) | |||
1355 | phyid = asix_get_phyid(dev); | 1410 | phyid = asix_get_phyid(dev); |
1356 | dbg("PHYID=0x%08x", phyid); | 1411 | dbg("PHYID=0x%08x", phyid); |
1357 | 1412 | ||
1358 | if (data->phymode == PHY_MODE_MARVELL) { | 1413 | ret = ax88178_reset(dev); |
1359 | marvell_phy_init(dev); | 1414 | if (ret < 0) |
1360 | msleep(60); | ||
1361 | } | ||
1362 | |||
1363 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, | ||
1364 | BMCR_RESET | BMCR_ANENABLE); | ||
1365 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, | ||
1366 | ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); | ||
1367 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_CTRL1000, | ||
1368 | ADVERTISE_1000FULL); | ||
1369 | |||
1370 | mii_nway_restart(&dev->mii); | ||
1371 | |||
1372 | if ((ret = asix_write_medium_mode(dev, AX88178_MEDIUM_DEFAULT)) < 0) | ||
1373 | goto out; | ||
1374 | |||
1375 | if ((ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) < 0) | ||
1376 | goto out; | 1415 | goto out; |
1377 | 1416 | ||
1378 | /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */ | 1417 | /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */ |
@@ -1443,7 +1482,7 @@ static const struct driver_info ax88178_info = { | |||
1443 | .bind = ax88178_bind, | 1482 | .bind = ax88178_bind, |
1444 | .status = asix_status, | 1483 | .status = asix_status, |
1445 | .link_reset = ax88178_link_reset, | 1484 | .link_reset = ax88178_link_reset, |
1446 | .reset = ax88178_link_reset, | 1485 | .reset = ax88178_reset, |
1447 | .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR, | 1486 | .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR, |
1448 | .rx_fixup = asix_rx_fixup, | 1487 | .rx_fixup = asix_rx_fixup, |
1449 | .tx_fixup = asix_tx_fixup, | 1488 | .tx_fixup = asix_tx_fixup, |