1 From b55de80e49892002a1878013ab9aee1a30970be6 Mon Sep 17 00:00:00 2001
2 From: Bruce Allan <bruce.w.allan@intel.com>
3 Date: Sat, 21 Mar 2009 13:25:25 -0700
4 Subject: [PATCH] e100: add support for 82552 10/100 adapter
6 This patch enables support for the new Intel 82552 adapter (new PHY paired
7 with the existing MAC in the ICH7 chipset). No new features are added to
8 the driver, however there are minor changes due to updated registers and a
9 few workarounds for hardware errata.
11 Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
12 Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
13 Signed-off-by: David S. Miller <davem@davemloft.net>
15 drivers/net/e100.c | 93 +++++++++++++++++++++++++++++++++++++++++++---------
16 1 files changed, 77 insertions(+), 16 deletions(-)
18 diff --git a/drivers/net/e100.c b/drivers/net/e100.c
19 index 861d2ee..0504db9 100644
20 --- a/drivers/net/e100.c
21 +++ b/drivers/net/e100.c
24 #define DRV_NAME "e100"
25 #define DRV_EXT "-NAPI"
26 -#define DRV_VERSION "3.5.23-k6"DRV_EXT
27 +#define DRV_VERSION "3.5.24-k2"DRV_EXT
28 #define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver"
29 #define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation"
30 #define PFX DRV_NAME ": "
31 @@ -240,6 +240,7 @@ static struct pci_device_id e100_id_table[] = {
32 INTEL_8255X_ETHERNET_DEVICE(0x1093, 7),
33 INTEL_8255X_ETHERNET_DEVICE(0x1094, 7),
34 INTEL_8255X_ETHERNET_DEVICE(0x1095, 7),
35 + INTEL_8255X_ETHERNET_DEVICE(0x10fe, 7),
36 INTEL_8255X_ETHERNET_DEVICE(0x1209, 0),
37 INTEL_8255X_ETHERNET_DEVICE(0x1229, 0),
38 INTEL_8255X_ETHERNET_DEVICE(0x2449, 2),
39 @@ -275,6 +276,7 @@ enum phy {
40 phy_82562_em = 0x032002A8,
41 phy_82562_ek = 0x031002A8,
42 phy_82562_eh = 0x017002A8,
43 + phy_82552_v = 0xd061004d,
44 phy_unknown = 0xFFFFFFFF,
47 @@ -943,6 +945,22 @@ static int mdio_read(struct net_device *netdev, int addr, int reg)
49 static void mdio_write(struct net_device *netdev, int addr, int reg, int data)
51 + struct nic *nic = netdev_priv(netdev);
53 + if ((nic->phy == phy_82552_v) && (reg == MII_BMCR) &&
54 + (data & (BMCR_ANRESTART | BMCR_ANENABLE))) {
55 + u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE);
58 + * Workaround Si issue where sometimes the part will not
59 + * autoneg to 100Mbps even when advertised.
61 + if (advert & ADVERTISE_100FULL)
62 + data |= BMCR_SPEED100 | BMCR_FULLDPLX;
63 + else if (advert & ADVERTISE_100HALF)
64 + data |= BMCR_SPEED100;
67 mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data);
70 @@ -1276,16 +1294,12 @@ static int e100_phy_init(struct nic *nic)
74 - /* Selected the phy and isolate the rest */
75 - for (addr = 0; addr < 32; addr++) {
76 - if (addr != nic->mii.phy_id) {
77 - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE);
79 - bmcr = mdio_read(netdev, addr, MII_BMCR);
80 - mdio_write(netdev, addr, MII_BMCR,
81 - bmcr & ~BMCR_ISOLATE);
84 + /* Isolate all the PHY ids */
85 + for (addr = 0; addr < 32; addr++)
86 + mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE);
87 + /* Select the discovered PHY */
88 + bmcr &= ~BMCR_ISOLATE;
89 + mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr);
92 id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1);
93 @@ -1303,7 +1317,18 @@ static int e100_phy_init(struct nic *nic)
94 mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong);
97 - if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
98 + if (nic->phy == phy_82552_v) {
99 + u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE);
101 + /* Workaround Si not advertising flow-control during autoneg */
102 + advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
103 + mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert);
105 + /* Reset for the above changes to take effect */
106 + bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR);
107 + bmcr |= BMCR_RESET;
108 + mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr);
109 + } else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
110 (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) &&
111 !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) {
112 /* enable/disable MDI/MDI-X auto-switching. */
113 @@ -2134,6 +2159,9 @@ err_clean_rx:
116 #define MII_LED_CONTROL 0x1B
117 +#define E100_82552_LED_OVERRIDE 0x19
118 +#define E100_82552_LED_ON 0x000F /* LEDTX and LED_RX both on */
119 +#define E100_82552_LED_OFF 0x000A /* LEDTX and LED_RX both off */
120 static void e100_blink_led(unsigned long data)
122 struct nic *nic = (struct nic *)data;
123 @@ -2143,10 +2171,19 @@ static void e100_blink_led(unsigned long data)
127 + u16 led_reg = MII_LED_CONTROL;
129 + if (nic->phy == phy_82552_v) {
130 + led_reg = E100_82552_LED_OVERRIDE;
132 - nic->leds = (nic->leds & led_on) ? led_off :
133 - (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559;
134 - mdio_write(nic->netdev, nic->mii.phy_id, MII_LED_CONTROL, nic->leds);
135 + nic->leds = (nic->leds == E100_82552_LED_ON) ?
136 + E100_82552_LED_OFF : E100_82552_LED_ON;
138 + nic->leds = (nic->leds & led_on) ? led_off :
139 + (nic->mac < mac_82559_D101M) ? led_on_557 :
142 + mdio_write(nic->netdev, nic->mii.phy_id, led_reg, nic->leds);
143 mod_timer(&nic->blink_timer, jiffies + HZ / 4);
146 @@ -2375,13 +2412,15 @@ static void e100_diag_test(struct net_device *netdev,
147 static int e100_phys_id(struct net_device *netdev, u32 data)
149 struct nic *nic = netdev_priv(netdev);
150 + u16 led_reg = (nic->phy == phy_82552_v) ? E100_82552_LED_OVERRIDE :
153 if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
154 data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
155 mod_timer(&nic->blink_timer, jiffies);
156 msleep_interruptible(data * 1000);
157 del_timer_sync(&nic->blink_timer);
158 - mdio_write(netdev, nic->mii.phy_id, MII_LED_CONTROL, 0);
159 + mdio_write(netdev, nic->mii.phy_id, led_reg, 0);
163 @@ -2686,6 +2725,9 @@ static void __devexit e100_remove(struct pci_dev *pdev)
167 +#define E100_82552_SMARTSPEED 0x14 /* SmartSpeed Ctrl register */
168 +#define E100_82552_REV_ANEG 0x0200 /* Reverse auto-negotiation */
169 +#define E100_82552_ANEG_NOW 0x0400 /* Auto-negotiate now */
170 static int e100_suspend(struct pci_dev *pdev, pm_message_t state)
172 struct net_device *netdev = pci_get_drvdata(pdev);
173 @@ -2698,6 +2740,15 @@ static int e100_suspend(struct pci_dev *pdev, pm_message_t state)
174 pci_save_state(pdev);
176 if ((nic->flags & wol_magic) | e100_asf(nic)) {
177 + /* enable reverse auto-negotiation */
178 + if (nic->phy == phy_82552_v) {
179 + u16 smartspeed = mdio_read(netdev, nic->mii.phy_id,
180 + E100_82552_SMARTSPEED);
182 + mdio_write(netdev, nic->mii.phy_id,
183 + E100_82552_SMARTSPEED, smartspeed |
184 + E100_82552_REV_ANEG | E100_82552_ANEG_NOW);
186 if (pci_enable_wake(pdev, PCI_D3cold, true))
187 pci_enable_wake(pdev, PCI_D3hot, true);
189 @@ -2721,6 +2772,16 @@ static int e100_resume(struct pci_dev *pdev)
190 /* ack any pending wake events, disable PME */
191 pci_enable_wake(pdev, 0, 0);
193 + /* disbale reverse auto-negotiation */
194 + if (nic->phy == phy_82552_v) {
195 + u16 smartspeed = mdio_read(netdev, nic->mii.phy_id,
196 + E100_82552_SMARTSPEED);
198 + mdio_write(netdev, nic->mii.phy_id,
199 + E100_82552_SMARTSPEED,
200 + smartspeed & ~(E100_82552_REV_ANEG));
203 netif_device_attach(netdev);
204 if (netif_running(netdev))