upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / net / sfc / mdio_10g.c
1 /****************************************************************************
2  * Driver for Solarflare Solarstorm network controllers and boards
3  * Copyright 2006-2009 Solarflare Communications Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 as published
7  * by the Free Software Foundation, incorporated herein by reference.
8  */
9 /*
10  * Useful functions for working with MDIO clause 45 PHYs
11  */
12 #include <linux/types.h>
13 #include <linux/ethtool.h>
14 #include <linux/delay.h>
15 #include "net_driver.h"
16 #include "mdio_10g.h"
17 #include "workarounds.h"
18 #include "nic.h"
19
20 unsigned efx_mdio_id_oui(u32 id)
21 {
22         unsigned oui = 0;
23         int i;
24
25         /* The bits of the OUI are designated a..x, with a=0 and b variable.
26          * In the id register c is the MSB but the OUI is conventionally
27          * written as bytes h..a, p..i, x..q.  Reorder the bits accordingly. */
28         for (i = 0; i < 22; ++i)
29                 if (id & (1 << (i + 10)))
30                         oui |= 1 << (i ^ 7);
31
32         return oui;
33 }
34
35 int efx_mdio_reset_mmd(struct efx_nic *port, int mmd,
36                             int spins, int spintime)
37 {
38         u32 ctrl;
39
40         /* Catch callers passing values in the wrong units (or just silly) */
41         EFX_BUG_ON_PARANOID(spins * spintime >= 5000);
42
43         efx_mdio_write(port, mmd, MDIO_CTRL1, MDIO_CTRL1_RESET);
44         /* Wait for the reset bit to clear. */
45         do {
46                 msleep(spintime);
47                 ctrl = efx_mdio_read(port, mmd, MDIO_CTRL1);
48                 spins--;
49
50         } while (spins && (ctrl & MDIO_CTRL1_RESET));
51
52         return spins ? spins : -ETIMEDOUT;
53 }
54
55 static int efx_mdio_check_mmd(struct efx_nic *efx, int mmd, int fault_fatal)
56 {
57         int status;
58
59         if (LOOPBACK_INTERNAL(efx))
60                 return 0;
61
62         if (mmd != MDIO_MMD_AN) {
63                 /* Read MMD STATUS2 to check it is responding. */
64                 status = efx_mdio_read(efx, mmd, MDIO_STAT2);
65                 if ((status & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL) {
66                         netif_err(efx, hw, efx->net_dev,
67                                   "PHY MMD %d not responding.\n", mmd);
68                         return -EIO;
69                 }
70         }
71
72         /* Read MMD STATUS 1 to check for fault. */
73         status = efx_mdio_read(efx, mmd, MDIO_STAT1);
74         if (status & MDIO_STAT1_FAULT) {
75                 if (fault_fatal) {
76                         netif_err(efx, hw, efx->net_dev,
77                                   "PHY MMD %d reporting fatal"
78                                   " fault: status %x\n", mmd, status);
79                         return -EIO;
80                 } else {
81                         netif_dbg(efx, hw, efx->net_dev,
82                                   "PHY MMD %d reporting status"
83                                   " %x (expected)\n", mmd, status);
84                 }
85         }
86         return 0;
87 }
88
89 /* This ought to be ridiculous overkill. We expect it to fail rarely */
90 #define MDIO45_RESET_TIME       1000 /* ms */
91 #define MDIO45_RESET_ITERS      100
92
93 int efx_mdio_wait_reset_mmds(struct efx_nic *efx, unsigned int mmd_mask)
94 {
95         const int spintime = MDIO45_RESET_TIME / MDIO45_RESET_ITERS;
96         int tries = MDIO45_RESET_ITERS;
97         int rc = 0;
98         int in_reset;
99
100         while (tries) {
101                 int mask = mmd_mask;
102                 int mmd = 0;
103                 int stat;
104                 in_reset = 0;
105                 while (mask) {
106                         if (mask & 1) {
107                                 stat = efx_mdio_read(efx, mmd, MDIO_CTRL1);
108                                 if (stat < 0) {
109                                         netif_err(efx, hw, efx->net_dev,
110                                                   "failed to read status of"
111                                                   " MMD %d\n", mmd);
112                                         return -EIO;
113                                 }
114                                 if (stat & MDIO_CTRL1_RESET)
115                                         in_reset |= (1 << mmd);
116                         }
117                         mask = mask >> 1;
118                         mmd++;
119                 }
120                 if (!in_reset)
121                         break;
122                 tries--;
123                 msleep(spintime);
124         }
125         if (in_reset != 0) {
126                 netif_err(efx, hw, efx->net_dev,
127                           "not all MMDs came out of reset in time."
128                           " MMDs still in reset: %x\n", in_reset);
129                 rc = -ETIMEDOUT;
130         }
131         return rc;
132 }
133
134 int efx_mdio_check_mmds(struct efx_nic *efx,
135                         unsigned int mmd_mask, unsigned int fatal_mask)
136 {
137         int mmd = 0, probe_mmd, devs1, devs2;
138         u32 devices;
139
140         /* Historically we have probed the PHYXS to find out what devices are
141          * present,but that doesn't work so well if the PHYXS isn't expected
142          * to exist, if so just find the first item in the list supplied. */
143         probe_mmd = (mmd_mask & MDIO_DEVS_PHYXS) ? MDIO_MMD_PHYXS :
144             __ffs(mmd_mask);
145
146         /* Check all the expected MMDs are present */
147         devs1 = efx_mdio_read(efx, probe_mmd, MDIO_DEVS1);
148         devs2 = efx_mdio_read(efx, probe_mmd, MDIO_DEVS2);
149         if (devs1 < 0 || devs2 < 0) {
150                 netif_err(efx, hw, efx->net_dev,
151                           "failed to read devices present\n");
152                 return -EIO;
153         }
154         devices = devs1 | (devs2 << 16);
155         if ((devices & mmd_mask) != mmd_mask) {
156                 netif_err(efx, hw, efx->net_dev,
157                           "required MMDs not present: got %x, wanted %x\n",
158                           devices, mmd_mask);
159                 return -ENODEV;
160         }
161         netif_vdbg(efx, hw, efx->net_dev, "Devices present: %x\n", devices);
162
163         /* Check all required MMDs are responding and happy. */
164         while (mmd_mask) {
165                 if (mmd_mask & 1) {
166                         int fault_fatal = fatal_mask & 1;
167                         if (efx_mdio_check_mmd(efx, mmd, fault_fatal))
168                                 return -EIO;
169                 }
170                 mmd_mask = mmd_mask >> 1;
171                 fatal_mask = fatal_mask >> 1;
172                 mmd++;
173         }
174
175         return 0;
176 }
177
178 bool efx_mdio_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
179 {
180         /* If the port is in loopback, then we should only consider a subset
181          * of mmd's */
182         if (LOOPBACK_INTERNAL(efx))
183                 return true;
184         else if (LOOPBACK_MASK(efx) & LOOPBACKS_WS)
185                 return false;
186         else if (efx_phy_mode_disabled(efx->phy_mode))
187                 return false;
188         else if (efx->loopback_mode == LOOPBACK_PHYXS)
189                 mmd_mask &= ~(MDIO_DEVS_PHYXS |
190                               MDIO_DEVS_PCS |
191                               MDIO_DEVS_PMAPMD |
192                               MDIO_DEVS_AN);
193         else if (efx->loopback_mode == LOOPBACK_PCS)
194                 mmd_mask &= ~(MDIO_DEVS_PCS |
195                               MDIO_DEVS_PMAPMD |
196                               MDIO_DEVS_AN);
197         else if (efx->loopback_mode == LOOPBACK_PMAPMD)
198                 mmd_mask &= ~(MDIO_DEVS_PMAPMD |
199                               MDIO_DEVS_AN);
200
201         return mdio45_links_ok(&efx->mdio, mmd_mask);
202 }
203
204 void efx_mdio_transmit_disable(struct efx_nic *efx)
205 {
206         efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD,
207                           MDIO_PMA_TXDIS, MDIO_PMD_TXDIS_GLOBAL,
208                           efx->phy_mode & PHY_MODE_TX_DISABLED);
209 }
210
211 void efx_mdio_phy_reconfigure(struct efx_nic *efx)
212 {
213         efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD,
214                           MDIO_CTRL1, MDIO_PMA_CTRL1_LOOPBACK,
215                           efx->loopback_mode == LOOPBACK_PMAPMD);
216         efx_mdio_set_flag(efx, MDIO_MMD_PCS,
217                           MDIO_CTRL1, MDIO_PCS_CTRL1_LOOPBACK,
218                           efx->loopback_mode == LOOPBACK_PCS);
219         efx_mdio_set_flag(efx, MDIO_MMD_PHYXS,
220                           MDIO_CTRL1, MDIO_PHYXS_CTRL1_LOOPBACK,
221                           efx->loopback_mode == LOOPBACK_PHYXS_WS);
222 }
223
224 static void efx_mdio_set_mmd_lpower(struct efx_nic *efx,
225                                     int lpower, int mmd)
226 {
227         int stat = efx_mdio_read(efx, mmd, MDIO_STAT1);
228
229         netif_vdbg(efx, drv, efx->net_dev, "Setting low power mode for MMD %d to %d\n",
230                   mmd, lpower);
231
232         if (stat & MDIO_STAT1_LPOWERABLE) {
233                 efx_mdio_set_flag(efx, mmd, MDIO_CTRL1,
234                                   MDIO_CTRL1_LPOWER, lpower);
235         }
236 }
237
238 void efx_mdio_set_mmds_lpower(struct efx_nic *efx,
239                               int low_power, unsigned int mmd_mask)
240 {
241         int mmd = 0;
242         mmd_mask &= ~MDIO_DEVS_AN;
243         while (mmd_mask) {
244                 if (mmd_mask & 1)
245                         efx_mdio_set_mmd_lpower(efx, low_power, mmd);
246                 mmd_mask = (mmd_mask >> 1);
247                 mmd++;
248         }
249 }
250
251 /**
252  * efx_mdio_set_settings - Set (some of) the PHY settings over MDIO.
253  * @efx:                Efx NIC
254  * @ecmd:               New settings
255  */
256 int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
257 {
258         struct ethtool_cmd prev;
259
260         efx->phy_op->get_settings(efx, &prev);
261
262         if (ecmd->advertising == prev.advertising &&
263             ecmd->speed == prev.speed &&
264             ecmd->duplex == prev.duplex &&
265             ecmd->port == prev.port &&
266             ecmd->autoneg == prev.autoneg)
267                 return 0;
268
269         /* We can only change these settings for -T PHYs */
270         if (prev.port != PORT_TP || ecmd->port != PORT_TP)
271                 return -EINVAL;
272
273         /* Check that PHY supports these settings */
274         if (!ecmd->autoneg ||
275             (ecmd->advertising | SUPPORTED_Autoneg) & ~prev.supported)
276                 return -EINVAL;
277
278         efx_link_set_advertising(efx, ecmd->advertising | ADVERTISED_Autoneg);
279         efx_mdio_an_reconfigure(efx);
280         return 0;
281 }
282
283 /**
284  * efx_mdio_an_reconfigure - Push advertising flags and restart autonegotiation
285  * @efx:                Efx NIC
286  */
287 void efx_mdio_an_reconfigure(struct efx_nic *efx)
288 {
289         bool xnp = (efx->link_advertising & ADVERTISED_10000baseT_Full
290                     || EFX_WORKAROUND_13204(efx));
291         int reg;
292
293         WARN_ON(!(efx->mdio.mmds & MDIO_DEVS_AN));
294
295         /* Set up the base page */
296         reg = ADVERTISE_CSMA;
297         if (efx->link_advertising & ADVERTISED_10baseT_Half)
298                 reg |= ADVERTISE_10HALF;
299         if (efx->link_advertising & ADVERTISED_10baseT_Full)
300                 reg |= ADVERTISE_10FULL;
301         if (efx->link_advertising & ADVERTISED_100baseT_Half)
302                 reg |= ADVERTISE_100HALF;
303         if (efx->link_advertising & ADVERTISED_100baseT_Full)
304                 reg |= ADVERTISE_100FULL;
305         if (xnp)
306                 reg |= ADVERTISE_RESV;
307         else if (efx->link_advertising & (ADVERTISED_1000baseT_Half |
308                                           ADVERTISED_1000baseT_Full))
309                 reg |= ADVERTISE_NPAGE;
310         if (efx->link_advertising & ADVERTISED_Pause)
311                 reg |= ADVERTISE_PAUSE_CAP;
312         if (efx->link_advertising & ADVERTISED_Asym_Pause)
313                 reg |= ADVERTISE_PAUSE_ASYM;
314         efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg);
315
316         /* Set up the (extended) next page if necessary */
317         if (efx->phy_op->set_npage_adv)
318                 efx->phy_op->set_npage_adv(efx, efx->link_advertising);
319
320         /* Enable and restart AN */
321         reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1);
322         reg |= MDIO_AN_CTRL1_ENABLE;
323         if (!(EFX_WORKAROUND_15195(efx) && LOOPBACK_EXTERNAL(efx)))
324                 reg |= MDIO_AN_CTRL1_RESTART;
325         if (xnp)
326                 reg |= MDIO_AN_CTRL1_XNP;
327         else
328                 reg &= ~MDIO_AN_CTRL1_XNP;
329         efx_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg);
330 }
331
332 enum efx_fc_type efx_mdio_get_pause(struct efx_nic *efx)
333 {
334         BUILD_BUG_ON(EFX_FC_AUTO & (EFX_FC_RX | EFX_FC_TX));
335
336         if (!(efx->wanted_fc & EFX_FC_AUTO))
337                 return efx->wanted_fc;
338
339         WARN_ON(!(efx->mdio.mmds & MDIO_DEVS_AN));
340
341         return mii_resolve_flowctrl_fdx(
342                 mii_advertise_flowctrl(efx->wanted_fc),
343                 efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_LPA));
344 }
345
346 int efx_mdio_test_alive(struct efx_nic *efx)
347 {
348         int rc;
349         int devad = __ffs(efx->mdio.mmds);
350         u16 physid1, physid2;
351
352         mutex_lock(&efx->mac_lock);
353
354         physid1 = efx_mdio_read(efx, devad, MDIO_DEVID1);
355         physid2 = efx_mdio_read(efx, devad, MDIO_DEVID2);
356
357         if ((physid1 == 0x0000) || (physid1 == 0xffff) ||
358             (physid2 == 0x0000) || (physid2 == 0xffff)) {
359                 netif_err(efx, hw, efx->net_dev,
360                           "no MDIO PHY present with ID %d\n", efx->mdio.prtad);
361                 rc = -EINVAL;
362         } else {
363                 rc = efx_mdio_check_mmds(efx, efx->mdio.mmds, 0);
364         }
365
366         mutex_unlock(&efx->mac_lock);
367         return rc;
368 }