]> code.ossystems Code Review - openembedded-core.git/blob
9291362f0438740944b963aaa3549620be1369bc
[openembedded-core.git] /
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
5
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.
10
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>
14 ---
15  drivers/net/e100.c |   93 +++++++++++++++++++++++++++++++++++++++++++---------
16  1 files changed, 77 insertions(+), 16 deletions(-)
17
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
22 @@ -167,7 +167,7 @@
23  
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,
45  };
46  
47 @@ -943,6 +945,22 @@ static int mdio_read(struct net_device *netdev, int addr, int reg)
48  
49  static void mdio_write(struct net_device *netdev, int addr, int reg, int data)
50  {
51 +       struct nic *nic = netdev_priv(netdev);
52 +
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);
56 +
57 +               /*
58 +                * Workaround Si issue where sometimes the part will not
59 +                * autoneg to 100Mbps even when advertised.
60 +                */
61 +               if (advert & ADVERTISE_100FULL)
62 +                       data |= BMCR_SPEED100 | BMCR_FULLDPLX;
63 +               else if (advert & ADVERTISE_100HALF)
64 +                       data |= BMCR_SPEED100;
65 +       }
66 +
67         mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data);
68  }
69  
70 @@ -1276,16 +1294,12 @@ static int e100_phy_init(struct nic *nic)
71         if (addr == 32)
72                 return -EAGAIN;
73  
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);
78 -               } else {
79 -                       bmcr = mdio_read(netdev, addr, MII_BMCR);
80 -                       mdio_write(netdev, addr, MII_BMCR,
81 -                               bmcr & ~BMCR_ISOLATE);
82 -               }
83 -       }
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);
90  
91         /* Get phy ID */
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);
95         }
96  
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);
100 +
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);
104 +
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:
114  }
115  
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)
121  {
122         struct nic *nic = (struct nic *)data;
123 @@ -2143,10 +2171,19 @@ static void e100_blink_led(unsigned long data)
124                 led_on_559 = 0x05,
125                 led_on_557 = 0x07,
126         };
127 +       u16 led_reg = MII_LED_CONTROL;
128 +
129 +       if (nic->phy == phy_82552_v) {
130 +               led_reg = E100_82552_LED_OVERRIDE;
131  
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;
137 +       } else {
138 +               nic->leds = (nic->leds & led_on) ? led_off :
139 +                           (nic->mac < mac_82559_D101M) ? led_on_557 :
140 +                           led_on_559;
141 +       }
142 +       mdio_write(nic->netdev, nic->mii.phy_id, led_reg, nic->leds);
143         mod_timer(&nic->blink_timer, jiffies + HZ / 4);
144  }
145  
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)
148  {
149         struct nic *nic = netdev_priv(netdev);
150 +       u16 led_reg = (nic->phy == phy_82552_v) ? E100_82552_LED_OVERRIDE :
151 +                     MII_LED_CONTROL;
152  
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);
160  
161         return 0;
162  }
163 @@ -2686,6 +2725,9 @@ static void __devexit e100_remove(struct pci_dev *pdev)
164         }
165  }
166  
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)
171  {
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);
175  
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);
181 +
182 +                       mdio_write(netdev, nic->mii.phy_id,
183 +                                  E100_82552_SMARTSPEED, smartspeed |
184 +                                  E100_82552_REV_ANEG | E100_82552_ANEG_NOW);
185 +               }
186                 if (pci_enable_wake(pdev, PCI_D3cold, true))
187                         pci_enable_wake(pdev, PCI_D3hot, true);
188         } else {
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);
192  
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);
197 +
198 +               mdio_write(netdev, nic->mii.phy_id,
199 +                          E100_82552_SMARTSPEED,
200 +                          smartspeed & ~(E100_82552_REV_ANEG));
201 +       }
202 +
203         netif_device_attach(netdev);
204         if (netif_running(netdev))
205                 e100_up(nic);
206 -- 
207 1.5.5.1
208