summaryrefslogtreecommitdiffstats
path: root/kernel/drivers/net/ethernet/dlink/dl2k.c
diff options
context:
space:
mode:
authorJosé Pekkarinen <jose.pekkarinen@nokia.com>2016-04-11 10:41:07 +0300
committerJosé Pekkarinen <jose.pekkarinen@nokia.com>2016-04-13 08:17:18 +0300
commite09b41010ba33a20a87472ee821fa407a5b8da36 (patch)
treed10dc367189862e7ca5c592f033dc3726e1df4e3 /kernel/drivers/net/ethernet/dlink/dl2k.c
parentf93b97fd65072de626c074dbe099a1fff05ce060 (diff)
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
are taken from kernel.org, and rt patch from the rt wiki download page. During the rebasing, the following patch collided: Force tick interrupt and get rid of softirq magic(I70131fb85). Collisions have been removed because its logic was found on the source already. Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769 Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'kernel/drivers/net/ethernet/dlink/dl2k.c')
-rw-r--r--kernel/drivers/net/ethernet/dlink/dl2k.c59
1 files changed, 53 insertions, 6 deletions
diff --git a/kernel/drivers/net/ethernet/dlink/dl2k.c b/kernel/drivers/net/ethernet/dlink/dl2k.c
index 1274b6fda..ccca4799c 100644
--- a/kernel/drivers/net/ethernet/dlink/dl2k.c
+++ b/kernel/drivers/net/ethernet/dlink/dl2k.c
@@ -253,6 +253,19 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
if (err)
goto err_out_unmap_rx;
+ if (np->chip_id == CHIP_IP1000A &&
+ (np->pdev->revision == 0x40 || np->pdev->revision == 0x41)) {
+ /* PHY magic taken from ipg driver, undocumented registers */
+ mii_write(dev, np->phy_addr, 31, 0x0001);
+ mii_write(dev, np->phy_addr, 27, 0x01e0);
+ mii_write(dev, np->phy_addr, 31, 0x0002);
+ mii_write(dev, np->phy_addr, 27, 0xeb8e);
+ mii_write(dev, np->phy_addr, 31, 0x0000);
+ mii_write(dev, np->phy_addr, 30, 0x005e);
+ /* advertise 1000BASE-T half & full duplex, prefer MASTER */
+ mii_write(dev, np->phy_addr, MII_CTRL1000, 0x0700);
+ }
+
/* Fiber device? */
np->phy_media = (dr16(ASICCtrl) & PhyMedia) ? 1 : 0;
np->link_status = 0;
@@ -361,6 +374,11 @@ parse_eeprom (struct net_device *dev)
for (i = 0; i < 6; i++)
dev->dev_addr[i] = psrom->mac_addr[i];
+ if (np->chip_id == CHIP_IP1000A) {
+ np->led_mode = psrom->led_mode;
+ return 0;
+ }
+
if (np->pdev->vendor != PCI_VENDOR_ID_DLINK) {
return 0;
}
@@ -406,6 +424,28 @@ parse_eeprom (struct net_device *dev)
return 0;
}
+static void rio_set_led_mode(struct net_device *dev)
+{
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->ioaddr;
+ u32 mode;
+
+ if (np->chip_id != CHIP_IP1000A)
+ return;
+
+ mode = dr32(ASICCtrl);
+ mode &= ~(IPG_AC_LED_MODE_BIT_1 | IPG_AC_LED_MODE | IPG_AC_LED_SPEED);
+
+ if (np->led_mode & 0x01)
+ mode |= IPG_AC_LED_MODE;
+ if (np->led_mode & 0x02)
+ mode |= IPG_AC_LED_MODE_BIT_1;
+ if (np->led_mode & 0x08)
+ mode |= IPG_AC_LED_SPEED;
+
+ dw32(ASICCtrl, mode);
+}
+
static int
rio_open (struct net_device *dev)
{
@@ -424,6 +464,8 @@ rio_open (struct net_device *dev)
GlobalReset | DMAReset | FIFOReset | NetworkReset | HostReset);
mdelay(10);
+ rio_set_led_mode(dev);
+
/* DebugCtrl bit 4, 5, 9 must set */
dw32(DebugCtrl, dr32(DebugCtrl) | 0x0230);
@@ -433,9 +475,13 @@ rio_open (struct net_device *dev)
alloc_list (dev);
- /* Get station address */
- for (i = 0; i < 6; i++)
- dw8(StationAddr0 + i, dev->dev_addr[i]);
+ /* Set station address */
+ /* 16 or 32-bit access is required by TC9020 datasheet but 8-bit works
+ * too. However, it doesn't work on IP1000A so we use 16-bit access.
+ */
+ for (i = 0; i < 3; i++)
+ dw16(StationAddr0 + 2 * i,
+ cpu_to_le16(((u16 *)dev->dev_addr)[i]));
set_multicast (dev);
if (np->coalesce) {
@@ -463,10 +509,8 @@ rio_open (struct net_device *dev)
dw32(MACCtrl, dr32(MACCtrl) | AutoVLANuntagging);
}
- init_timer (&np->timer);
+ setup_timer(&np->timer, rio_timer, (unsigned long)dev);
np->timer.expires = jiffies + 1*HZ;
- np->timer.data = (unsigned long) dev;
- np->timer.function = rio_timer;
add_timer (&np->timer);
/* Start Tx/Rx */
@@ -782,6 +826,7 @@ tx_error (struct net_device *dev, int tx_status)
break;
mdelay (1);
}
+ rio_set_led_mode(dev);
rio_free_tx (dev, 1);
/* Reset TFDListPtr */
dw32(TFDListPtr0, np->tx_ring_dma +
@@ -801,6 +846,7 @@ tx_error (struct net_device *dev, int tx_status)
break;
mdelay (1);
}
+ rio_set_led_mode(dev);
/* Let TxStartThresh stay default value */
}
/* Maximum Collisions */
@@ -967,6 +1013,7 @@ rio_error (struct net_device *dev, int int_status)
dev->name, int_status);
dw16(ASICCtrl + 2, GlobalReset | HostReset);
mdelay (500);
+ rio_set_led_mode(dev);
}
}