diff options
author | Ondrej Zary <linux@rainbow-software.org> | 2015-11-15 16:36:11 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-11-16 17:11:31 -0500 |
commit | c3f45d322cbd379c46466cc2ecab7e2d719b22ed (patch) | |
tree | f8bbc735fb79fbc7306dd4e96098c834aea58c9a | |
parent | 41033f029e393a64e81966cbe34d66c6cf8a2e7e (diff) |
dl2k: Add support for IP1000A-based cards
Add support for IP1000A chips to dl2k driver.
IP1000A chip looks like a TC9020 with integrated PHY.
This allows IP1000A chips to work reliably because the ipg driver is
buggy - it loses packets under load and then completely stops
transmitting data.
Tested with Asus NX1101 v2.0 at 10, 100 and 1000Mbps:
vendor=0x13f0 device=0x1023 (rev 0x41)
subsystem vendor=0x1043 device=0x8180
MAC address registers access needed to be changed from 8-bit to 16-bit
because 8-bit does not work on IP1000A. 8-bit access is not even
allowed in the TC9020 datasheet (although it worked). 16-bit access
works on both.
Tested that it does not break D-Link DGE-550T (DL-2000 chip, probably
a rebranded TC9020):
vendor=0x1186 device=0x4000 (rev 0x0c)
subsystem vendor=0x1186 device=0x4000
Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/dlink/Kconfig | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/dlink/dl2k.c | 55 | ||||
-rw-r--r-- | drivers/net/ethernet/dlink/dl2k.h | 15 |
3 files changed, 69 insertions, 6 deletions
diff --git a/drivers/net/ethernet/dlink/Kconfig b/drivers/net/ethernet/dlink/Kconfig index f6e858d0b9d4..ebdc83247bb6 100644 --- a/drivers/net/ethernet/dlink/Kconfig +++ b/drivers/net/ethernet/dlink/Kconfig | |||
@@ -17,15 +17,16 @@ config NET_VENDOR_DLINK | |||
17 | if NET_VENDOR_DLINK | 17 | if NET_VENDOR_DLINK |
18 | 18 | ||
19 | config DL2K | 19 | config DL2K |
20 | tristate "DL2000/TC902x-based Gigabit Ethernet support" | 20 | tristate "DL2000/TC902x/IP1000A-based Gigabit Ethernet support" |
21 | depends on PCI | 21 | depends on PCI |
22 | select CRC32 | 22 | select CRC32 |
23 | ---help--- | 23 | ---help--- |
24 | This driver supports DL2000/TC902x-based Gigabit ethernet cards, | 24 | This driver supports DL2000/TC902x/IP1000A-based Gigabit ethernet cards, |
25 | which includes | 25 | which includes |
26 | D-Link DGE-550T Gigabit Ethernet Adapter. | 26 | D-Link DGE-550T Gigabit Ethernet Adapter. |
27 | D-Link DL2000-based Gigabit Ethernet Adapter. | 27 | D-Link DL2000-based Gigabit Ethernet Adapter. |
28 | Sundance/Tamarack TC902x Gigabit Ethernet Adapter. | 28 | Sundance/Tamarack TC902x Gigabit Ethernet Adapter. |
29 | ICPlus IP1000A-based cards | ||
29 | 30 | ||
30 | To compile this driver as a module, choose M here: the | 31 | To compile this driver as a module, choose M here: the |
31 | module will be called dl2k. | 32 | module will be called dl2k. |
diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c index cf0a5fcdaaaf..ccca4799c27b 100644 --- a/drivers/net/ethernet/dlink/dl2k.c +++ b/drivers/net/ethernet/dlink/dl2k.c | |||
@@ -253,6 +253,19 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
253 | if (err) | 253 | if (err) |
254 | goto err_out_unmap_rx; | 254 | goto err_out_unmap_rx; |
255 | 255 | ||
256 | if (np->chip_id == CHIP_IP1000A && | ||
257 | (np->pdev->revision == 0x40 || np->pdev->revision == 0x41)) { | ||
258 | /* PHY magic taken from ipg driver, undocumented registers */ | ||
259 | mii_write(dev, np->phy_addr, 31, 0x0001); | ||
260 | mii_write(dev, np->phy_addr, 27, 0x01e0); | ||
261 | mii_write(dev, np->phy_addr, 31, 0x0002); | ||
262 | mii_write(dev, np->phy_addr, 27, 0xeb8e); | ||
263 | mii_write(dev, np->phy_addr, 31, 0x0000); | ||
264 | mii_write(dev, np->phy_addr, 30, 0x005e); | ||
265 | /* advertise 1000BASE-T half & full duplex, prefer MASTER */ | ||
266 | mii_write(dev, np->phy_addr, MII_CTRL1000, 0x0700); | ||
267 | } | ||
268 | |||
256 | /* Fiber device? */ | 269 | /* Fiber device? */ |
257 | np->phy_media = (dr16(ASICCtrl) & PhyMedia) ? 1 : 0; | 270 | np->phy_media = (dr16(ASICCtrl) & PhyMedia) ? 1 : 0; |
258 | np->link_status = 0; | 271 | np->link_status = 0; |
@@ -361,6 +374,11 @@ parse_eeprom (struct net_device *dev) | |||
361 | for (i = 0; i < 6; i++) | 374 | for (i = 0; i < 6; i++) |
362 | dev->dev_addr[i] = psrom->mac_addr[i]; | 375 | dev->dev_addr[i] = psrom->mac_addr[i]; |
363 | 376 | ||
377 | if (np->chip_id == CHIP_IP1000A) { | ||
378 | np->led_mode = psrom->led_mode; | ||
379 | return 0; | ||
380 | } | ||
381 | |||
364 | if (np->pdev->vendor != PCI_VENDOR_ID_DLINK) { | 382 | if (np->pdev->vendor != PCI_VENDOR_ID_DLINK) { |
365 | return 0; | 383 | return 0; |
366 | } | 384 | } |
@@ -406,6 +424,28 @@ parse_eeprom (struct net_device *dev) | |||
406 | return 0; | 424 | return 0; |
407 | } | 425 | } |
408 | 426 | ||
427 | static void rio_set_led_mode(struct net_device *dev) | ||
428 | { | ||
429 | struct netdev_private *np = netdev_priv(dev); | ||
430 | void __iomem *ioaddr = np->ioaddr; | ||
431 | u32 mode; | ||
432 | |||
433 | if (np->chip_id != CHIP_IP1000A) | ||
434 | return; | ||
435 | |||
436 | mode = dr32(ASICCtrl); | ||
437 | mode &= ~(IPG_AC_LED_MODE_BIT_1 | IPG_AC_LED_MODE | IPG_AC_LED_SPEED); | ||
438 | |||
439 | if (np->led_mode & 0x01) | ||
440 | mode |= IPG_AC_LED_MODE; | ||
441 | if (np->led_mode & 0x02) | ||
442 | mode |= IPG_AC_LED_MODE_BIT_1; | ||
443 | if (np->led_mode & 0x08) | ||
444 | mode |= IPG_AC_LED_SPEED; | ||
445 | |||
446 | dw32(ASICCtrl, mode); | ||
447 | } | ||
448 | |||
409 | static int | 449 | static int |
410 | rio_open (struct net_device *dev) | 450 | rio_open (struct net_device *dev) |
411 | { | 451 | { |
@@ -424,6 +464,8 @@ rio_open (struct net_device *dev) | |||
424 | GlobalReset | DMAReset | FIFOReset | NetworkReset | HostReset); | 464 | GlobalReset | DMAReset | FIFOReset | NetworkReset | HostReset); |
425 | mdelay(10); | 465 | mdelay(10); |
426 | 466 | ||
467 | rio_set_led_mode(dev); | ||
468 | |||
427 | /* DebugCtrl bit 4, 5, 9 must set */ | 469 | /* DebugCtrl bit 4, 5, 9 must set */ |
428 | dw32(DebugCtrl, dr32(DebugCtrl) | 0x0230); | 470 | dw32(DebugCtrl, dr32(DebugCtrl) | 0x0230); |
429 | 471 | ||
@@ -433,9 +475,13 @@ rio_open (struct net_device *dev) | |||
433 | 475 | ||
434 | alloc_list (dev); | 476 | alloc_list (dev); |
435 | 477 | ||
436 | /* Get station address */ | 478 | /* Set station address */ |
437 | for (i = 0; i < 6; i++) | 479 | /* 16 or 32-bit access is required by TC9020 datasheet but 8-bit works |
438 | dw8(StationAddr0 + i, dev->dev_addr[i]); | 480 | * too. However, it doesn't work on IP1000A so we use 16-bit access. |
481 | */ | ||
482 | for (i = 0; i < 3; i++) | ||
483 | dw16(StationAddr0 + 2 * i, | ||
484 | cpu_to_le16(((u16 *)dev->dev_addr)[i])); | ||
439 | 485 | ||
440 | set_multicast (dev); | 486 | set_multicast (dev); |
441 | if (np->coalesce) { | 487 | if (np->coalesce) { |
@@ -780,6 +826,7 @@ tx_error (struct net_device *dev, int tx_status) | |||
780 | break; | 826 | break; |
781 | mdelay (1); | 827 | mdelay (1); |
782 | } | 828 | } |
829 | rio_set_led_mode(dev); | ||
783 | rio_free_tx (dev, 1); | 830 | rio_free_tx (dev, 1); |
784 | /* Reset TFDListPtr */ | 831 | /* Reset TFDListPtr */ |
785 | dw32(TFDListPtr0, np->tx_ring_dma + | 832 | dw32(TFDListPtr0, np->tx_ring_dma + |
@@ -799,6 +846,7 @@ tx_error (struct net_device *dev, int tx_status) | |||
799 | break; | 846 | break; |
800 | mdelay (1); | 847 | mdelay (1); |
801 | } | 848 | } |
849 | rio_set_led_mode(dev); | ||
802 | /* Let TxStartThresh stay default value */ | 850 | /* Let TxStartThresh stay default value */ |
803 | } | 851 | } |
804 | /* Maximum Collisions */ | 852 | /* Maximum Collisions */ |
@@ -965,6 +1013,7 @@ rio_error (struct net_device *dev, int int_status) | |||
965 | dev->name, int_status); | 1013 | dev->name, int_status); |
966 | dw16(ASICCtrl + 2, GlobalReset | HostReset); | 1014 | dw16(ASICCtrl + 2, GlobalReset | HostReset); |
967 | mdelay (500); | 1015 | mdelay (500); |
1016 | rio_set_led_mode(dev); | ||
968 | } | 1017 | } |
969 | } | 1018 | } |
970 | 1019 | ||
diff --git a/drivers/net/ethernet/dlink/dl2k.h b/drivers/net/ethernet/dlink/dl2k.h index 23c07b007069..8f4f61262d5c 100644 --- a/drivers/net/ethernet/dlink/dl2k.h +++ b/drivers/net/ethernet/dlink/dl2k.h | |||
@@ -211,6 +211,10 @@ enum ASICCtrl_HiWord_bits { | |||
211 | ResetBusy = 0x0400, | 211 | ResetBusy = 0x0400, |
212 | }; | 212 | }; |
213 | 213 | ||
214 | #define IPG_AC_LED_MODE BIT(14) | ||
215 | #define IPG_AC_LED_SPEED BIT(27) | ||
216 | #define IPG_AC_LED_MODE_BIT_1 BIT(29) | ||
217 | |||
214 | /* Transmit Frame Control bits */ | 218 | /* Transmit Frame Control bits */ |
215 | enum TFC_bits { | 219 | enum TFC_bits { |
216 | DwordAlign = 0x00000000, | 220 | DwordAlign = 0x00000000, |
@@ -332,7 +336,10 @@ typedef struct t_SROM { | |||
332 | u16 asic_ctrl; /* 0x02 */ | 336 | u16 asic_ctrl; /* 0x02 */ |
333 | u16 sub_vendor_id; /* 0x04 */ | 337 | u16 sub_vendor_id; /* 0x04 */ |
334 | u16 sub_system_id; /* 0x06 */ | 338 | u16 sub_system_id; /* 0x06 */ |
335 | u16 reserved1[12]; /* 0x08-0x1f */ | 339 | u16 pci_base_1; /* 0x08 (IP1000A only) */ |
340 | u16 pci_base_2; /* 0x0a (IP1000A only) */ | ||
341 | u16 led_mode; /* 0x0c (IP1000A only) */ | ||
342 | u16 reserved1[9]; /* 0x0e-0x1f */ | ||
336 | u8 mac_addr[6]; /* 0x20-0x25 */ | 343 | u8 mac_addr[6]; /* 0x20-0x25 */ |
337 | u8 reserved2[10]; /* 0x26-0x2f */ | 344 | u8 reserved2[10]; /* 0x26-0x2f */ |
338 | u8 sib[204]; /* 0x30-0xfb */ | 345 | u8 sib[204]; /* 0x30-0xfb */ |
@@ -397,6 +404,7 @@ struct netdev_private { | |||
397 | u16 advertising; /* NWay media advertisement */ | 404 | u16 advertising; /* NWay media advertisement */ |
398 | u16 negotiate; /* Negotiated media */ | 405 | u16 negotiate; /* Negotiated media */ |
399 | int phy_addr; /* PHY addresses. */ | 406 | int phy_addr; /* PHY addresses. */ |
407 | u16 led_mode; /* LED mode read from EEPROM (IP1000A only) */ | ||
400 | }; | 408 | }; |
401 | 409 | ||
402 | /* The station address location in the EEPROM. */ | 410 | /* The station address location in the EEPROM. */ |
@@ -407,10 +415,15 @@ struct netdev_private { | |||
407 | class_mask of the class are honored during the comparison. | 415 | class_mask of the class are honored during the comparison. |
408 | driver_data Data private to the driver. | 416 | driver_data Data private to the driver. |
409 | */ | 417 | */ |
418 | #define CHIP_IP1000A 1 | ||
410 | 419 | ||
411 | static const struct pci_device_id rio_pci_tbl[] = { | 420 | static const struct pci_device_id rio_pci_tbl[] = { |
412 | {0x1186, 0x4000, PCI_ANY_ID, PCI_ANY_ID, }, | 421 | {0x1186, 0x4000, PCI_ANY_ID, PCI_ANY_ID, }, |
413 | {0x13f0, 0x1021, PCI_ANY_ID, PCI_ANY_ID, }, | 422 | {0x13f0, 0x1021, PCI_ANY_ID, PCI_ANY_ID, }, |
423 | { PCI_VDEVICE(SUNDANCE, 0x1023), CHIP_IP1000A }, | ||
424 | { PCI_VDEVICE(SUNDANCE, 0x2021), CHIP_IP1000A }, | ||
425 | { PCI_VDEVICE(DLINK, 0x9021), CHIP_IP1000A }, | ||
426 | { PCI_VDEVICE(DLINK, 0x4020), CHIP_IP1000A }, | ||
414 | { } | 427 | { } |
415 | }; | 428 | }; |
416 | MODULE_DEVICE_TABLE (pci, rio_pci_tbl); | 429 | MODULE_DEVICE_TABLE (pci, rio_pci_tbl); |