Merge branch 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6] / drivers / net / mdio.c
1 /*
2  * mdio.c: Generic support for MDIO-compatible transceivers
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 #include <linux/kernel.h>
11 #include <linux/capability.h>
12 #include <linux/errno.h>
13 #include <linux/ethtool.h>
14 #include <linux/mdio.h>
15 #include <linux/module.h>
16
17 MODULE_DESCRIPTION("Generic support for MDIO-compatible transceivers");
18 MODULE_AUTHOR("Copyright 2006-2009 Solarflare Communications Inc.");
19 MODULE_LICENSE("GPL");
20
21 /**
22  * mdio45_probe - probe for an MDIO (clause 45) device
23  * @mdio: MDIO interface
24  * @prtad: Expected PHY address
25  *
26  * This sets @prtad and @mmds in the MDIO interface if successful.
27  * Returns 0 on success, negative on error.
28  */
29 int mdio45_probe(struct mdio_if_info *mdio, int prtad)
30 {
31         int mmd, stat2, devs1, devs2;
32
33         /* Assume PHY must have at least one of PMA/PMD, WIS, PCS, PHY
34          * XS or DTE XS; give up if none is present. */
35         for (mmd = 1; mmd <= 5; mmd++) {
36                 /* Is this MMD present? */
37                 stat2 = mdio->mdio_read(mdio->dev, prtad, mmd, MDIO_STAT2);
38                 if (stat2 < 0 ||
39                     (stat2 & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL)
40                         continue;
41
42                 /* It should tell us about all the other MMDs */
43                 devs1 = mdio->mdio_read(mdio->dev, prtad, mmd, MDIO_DEVS1);
44                 devs2 = mdio->mdio_read(mdio->dev, prtad, mmd, MDIO_DEVS2);
45                 if (devs1 < 0 || devs2 < 0)
46                         continue;
47
48                 mdio->prtad = prtad;
49                 mdio->mmds = devs1 | (devs2 << 16);
50                 return 0;
51         }
52
53         return -ENODEV;
54 }
55 EXPORT_SYMBOL(mdio45_probe);
56
57 /**
58  * mdio_set_flag - set or clear flag in an MDIO register
59  * @mdio: MDIO interface
60  * @prtad: PHY address
61  * @devad: MMD address
62  * @addr: Register address
63  * @mask: Mask for flag (single bit set)
64  * @sense: New value of flag
65  *
66  * This debounces changes: it does not write the register if the flag
67  * already has the proper value.  Returns 0 on success, negative on error.
68  */
69 int mdio_set_flag(const struct mdio_if_info *mdio,
70                   int prtad, int devad, u16 addr, int mask,
71                   bool sense)
72 {
73         int old_val = mdio->mdio_read(mdio->dev, prtad, devad, addr);
74         int new_val;
75
76         if (old_val < 0)
77                 return old_val;
78         if (sense)
79                 new_val = old_val | mask;
80         else
81                 new_val = old_val & ~mask;
82         if (old_val == new_val)
83                 return 0;
84         return mdio->mdio_write(mdio->dev, prtad, devad, addr, new_val);
85 }
86 EXPORT_SYMBOL(mdio_set_flag);
87
88 /**
89  * mdio_link_ok - is link status up/OK
90  * @mdio: MDIO interface
91  * @mmd_mask: Mask for MMDs to check
92  *
93  * Returns 1 if the PHY reports link status up/OK, 0 otherwise.
94  * @mmd_mask is normally @mdio->mmds, but if loopback is enabled
95  * the MMDs being bypassed should be excluded from the mask.
96  */
97 int mdio45_links_ok(const struct mdio_if_info *mdio, u32 mmd_mask)
98 {
99         int devad, reg;
100
101         if (!mmd_mask) {
102                 /* Use absence of XGMII faults in lieu of link state */
103                 reg = mdio->mdio_read(mdio->dev, mdio->prtad,
104                                       MDIO_MMD_PHYXS, MDIO_STAT2);
105                 return reg >= 0 && !(reg & MDIO_STAT2_RXFAULT);
106         }
107
108         for (devad = 0; mmd_mask; devad++) {
109                 if (mmd_mask & (1 << devad)) {
110                         mmd_mask &= ~(1 << devad);
111
112                         /* Read twice because link state is latched and a
113                          * read moves the current state into the register */
114                         mdio->mdio_read(mdio->dev, mdio->prtad,
115                                         devad, MDIO_STAT1);
116                         reg = mdio->mdio_read(mdio->dev, mdio->prtad,
117                                               devad, MDIO_STAT1);
118                         if (reg < 0 || !(reg & MDIO_STAT1_LSTATUS))
119                                 return false;
120                 }
121         }
122
123         return true;
124 }
125 EXPORT_SYMBOL(mdio45_links_ok);
126
127 /**
128  * mdio45_nway_restart - restart auto-negotiation for this interface
129  * @mdio: MDIO interface
130  *
131  * Returns 0 on success, negative on error.
132  */
133 int mdio45_nway_restart(const struct mdio_if_info *mdio)
134 {
135         if (!(mdio->mmds & MDIO_DEVS_AN))
136                 return -EOPNOTSUPP;
137
138         mdio_set_flag(mdio, mdio->prtad, MDIO_MMD_AN, MDIO_CTRL1,
139                       MDIO_AN_CTRL1_RESTART, true);
140         return 0;
141 }
142 EXPORT_SYMBOL(mdio45_nway_restart);
143
144 static u32 mdio45_get_an(const struct mdio_if_info *mdio, u16 addr)
145 {
146         u32 result = 0;
147         int reg;
148
149         reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN, addr);
150         if (reg & ADVERTISE_10HALF)
151                 result |= ADVERTISED_10baseT_Half;
152         if (reg & ADVERTISE_10FULL)
153                 result |= ADVERTISED_10baseT_Full;
154         if (reg & ADVERTISE_100HALF)
155                 result |= ADVERTISED_100baseT_Half;
156         if (reg & ADVERTISE_100FULL)
157                 result |= ADVERTISED_100baseT_Full;
158         return result;
159 }
160
161 /**
162  * mdio45_ethtool_gset_npage - get settings for ETHTOOL_GSET
163  * @mdio: MDIO interface
164  * @ecmd: Ethtool request structure
165  * @npage_adv: Modes currently advertised on next pages
166  * @npage_lpa: Modes advertised by link partner on next pages
167  *
168  * Since the CSRs for auto-negotiation using next pages are not fully
169  * standardised, this function does not attempt to decode them.  The
170  * caller must pass them in.
171  */
172 void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio,
173                                struct ethtool_cmd *ecmd,
174                                u32 npage_adv, u32 npage_lpa)
175 {
176         int reg;
177
178         ecmd->transceiver = XCVR_INTERNAL;
179         ecmd->phy_address = mdio->prtad;
180         ecmd->mdio_support =
181                 mdio->mode_support & (MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22);
182
183         reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
184                               MDIO_CTRL2);
185         switch (reg & MDIO_PMA_CTRL2_TYPE) {
186         case MDIO_PMA_CTRL2_10GBT:
187         case MDIO_PMA_CTRL2_1000BT:
188         case MDIO_PMA_CTRL2_100BTX:
189         case MDIO_PMA_CTRL2_10BT:
190                 ecmd->port = PORT_TP;
191                 ecmd->supported = SUPPORTED_TP;
192                 reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
193                                       MDIO_SPEED);
194                 if (reg & MDIO_SPEED_10G)
195                         ecmd->supported |= SUPPORTED_10000baseT_Full;
196                 if (reg & MDIO_PMA_SPEED_1000)
197                         ecmd->supported |= (SUPPORTED_1000baseT_Full |
198                                             SUPPORTED_1000baseT_Half);
199                 if (reg & MDIO_PMA_SPEED_100)
200                         ecmd->supported |= (SUPPORTED_100baseT_Full |
201                                             SUPPORTED_100baseT_Half);
202                 if (reg & MDIO_PMA_SPEED_10)
203                         ecmd->supported |= (SUPPORTED_10baseT_Full |
204                                             SUPPORTED_10baseT_Half);
205                 ecmd->advertising = ADVERTISED_TP;
206                 break;
207
208         case MDIO_PMA_CTRL2_10GBCX4:
209                 ecmd->port = PORT_OTHER;
210                 ecmd->supported = 0;
211                 ecmd->advertising = 0;
212                 break;
213
214         case MDIO_PMA_CTRL2_10GBKX4:
215         case MDIO_PMA_CTRL2_10GBKR:
216         case MDIO_PMA_CTRL2_1000BKX:
217                 ecmd->port = PORT_OTHER;
218                 ecmd->supported = SUPPORTED_Backplane;
219                 reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
220                                       MDIO_PMA_EXTABLE);
221                 if (reg & MDIO_PMA_EXTABLE_10GBKX4)
222                         ecmd->supported |= SUPPORTED_10000baseKX4_Full;
223                 if (reg & MDIO_PMA_EXTABLE_10GBKR)
224                         ecmd->supported |= SUPPORTED_10000baseKR_Full;
225                 if (reg & MDIO_PMA_EXTABLE_1000BKX)
226                         ecmd->supported |= SUPPORTED_1000baseKX_Full;
227                 reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
228                                       MDIO_PMA_10GBR_FECABLE);
229                 if (reg & MDIO_PMA_10GBR_FECABLE_ABLE)
230                         ecmd->supported |= SUPPORTED_10000baseR_FEC;
231                 ecmd->advertising = ADVERTISED_Backplane;
232                 break;
233
234         /* All the other defined modes are flavours of optical */
235         default:
236                 ecmd->port = PORT_FIBRE;
237                 ecmd->supported = SUPPORTED_FIBRE;
238                 ecmd->advertising = ADVERTISED_FIBRE;
239                 break;
240         }
241
242         if (mdio->mmds & MDIO_DEVS_AN) {
243                 ecmd->supported |= SUPPORTED_Autoneg;
244                 reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN,
245                                       MDIO_CTRL1);
246                 if (reg & MDIO_AN_CTRL1_ENABLE) {
247                         ecmd->autoneg = AUTONEG_ENABLE;
248                         ecmd->advertising |=
249                                 ADVERTISED_Autoneg |
250                                 mdio45_get_an(mdio, MDIO_AN_ADVERTISE) |
251                                 npage_adv;
252                 } else {
253                         ecmd->autoneg = AUTONEG_DISABLE;
254                 }
255         } else {
256                 ecmd->autoneg = AUTONEG_DISABLE;
257         }
258
259         if (ecmd->autoneg) {
260                 u32 modes = 0;
261                 int an_stat = mdio->mdio_read(mdio->dev, mdio->prtad,
262                                               MDIO_MMD_AN, MDIO_STAT1);
263
264                 /* If AN is complete and successful, report best common
265                  * mode, otherwise report best advertised mode. */
266                 if (an_stat & MDIO_AN_STAT1_COMPLETE) {
267                         ecmd->lp_advertising =
268                                 mdio45_get_an(mdio, MDIO_AN_LPA) | npage_lpa;
269                         if (an_stat & MDIO_AN_STAT1_LPABLE)
270                                 ecmd->lp_advertising |= ADVERTISED_Autoneg;
271                         modes = ecmd->advertising & ecmd->lp_advertising;
272                 }
273                 if ((modes & ~ADVERTISED_Autoneg) == 0)
274                         modes = ecmd->advertising;
275
276                 if (modes & (ADVERTISED_10000baseT_Full |
277                              ADVERTISED_10000baseKX4_Full |
278                              ADVERTISED_10000baseKR_Full)) {
279                         ecmd->speed = SPEED_10000;
280                         ecmd->duplex = DUPLEX_FULL;
281                 } else if (modes & (ADVERTISED_1000baseT_Full |
282                                     ADVERTISED_1000baseT_Half |
283                                     ADVERTISED_1000baseKX_Full)) {
284                         ecmd->speed = SPEED_1000;
285                         ecmd->duplex = !(modes & ADVERTISED_1000baseT_Half);
286                 } else if (modes & (ADVERTISED_100baseT_Full |
287                                     ADVERTISED_100baseT_Half)) {
288                         ecmd->speed = SPEED_100;
289                         ecmd->duplex = !!(modes & ADVERTISED_100baseT_Full);
290                 } else {
291                         ecmd->speed = SPEED_10;
292                         ecmd->duplex = !!(modes & ADVERTISED_10baseT_Full);
293                 }
294         } else {
295                 /* Report forced settings */
296                 reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
297                                       MDIO_CTRL1);
298                 ecmd->speed = (((reg & MDIO_PMA_CTRL1_SPEED1000) ? 100 : 1) *
299                                ((reg & MDIO_PMA_CTRL1_SPEED100) ? 100 : 10));
300                 ecmd->duplex = (reg & MDIO_CTRL1_FULLDPLX ||
301                                 ecmd->speed == SPEED_10000);
302         }
303
304         /* 10GBASE-T MDI/MDI-X */
305         if (ecmd->port == PORT_TP && ecmd->speed == SPEED_10000) {
306                 switch (mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
307                                         MDIO_PMA_10GBT_SWAPPOL)) {
308                 case MDIO_PMA_10GBT_SWAPPOL_ABNX | MDIO_PMA_10GBT_SWAPPOL_CDNX:
309                         ecmd->eth_tp_mdix = ETH_TP_MDI;
310                         break;
311                 case 0:
312                         ecmd->eth_tp_mdix = ETH_TP_MDI_X;
313                         break;
314                 default:
315                         /* It's complicated... */
316                         ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
317                         break;
318                 }
319         }
320 }
321 EXPORT_SYMBOL(mdio45_ethtool_gset_npage);
322
323 /**
324  * mdio45_ethtool_spauseparam_an - set auto-negotiated pause parameters
325  * @mdio: MDIO interface
326  * @ecmd: Ethtool request structure
327  *
328  * This function assumes that the PHY has an auto-negotiation MMD.  It
329  * will enable and disable advertising of flow control as appropriate.
330  */
331 void mdio45_ethtool_spauseparam_an(const struct mdio_if_info *mdio,
332                                    const struct ethtool_pauseparam *ecmd)
333 {
334         int adv, old_adv;
335
336         WARN_ON(!(mdio->mmds & MDIO_DEVS_AN));
337
338         old_adv = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN,
339                                   MDIO_AN_ADVERTISE);
340         adv = old_adv & ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
341         if (ecmd->autoneg)
342                 adv |= mii_advertise_flowctrl(
343                         (ecmd->rx_pause ? FLOW_CTRL_RX : 0) |
344                         (ecmd->tx_pause ? FLOW_CTRL_TX : 0));
345         if (adv != old_adv) {
346                 mdio->mdio_write(mdio->dev, mdio->prtad, MDIO_MMD_AN,
347                                  MDIO_AN_ADVERTISE, adv);
348                 mdio45_nway_restart(mdio);
349         }
350 }
351 EXPORT_SYMBOL(mdio45_ethtool_spauseparam_an);
352
353 /**
354  * mdio_mii_ioctl - MII ioctl interface for MDIO (clause 22 or 45) PHYs
355  * @mdio: MDIO interface
356  * @mii_data: MII ioctl data structure
357  * @cmd: MII ioctl command
358  *
359  * Returns 0 on success, negative on error.
360  */
361 int mdio_mii_ioctl(const struct mdio_if_info *mdio,
362                    struct mii_ioctl_data *mii_data, int cmd)
363 {
364         int prtad, devad;
365         u16 addr = mii_data->reg_num;
366
367         /* Validate/convert cmd to one of SIOC{G,S}MIIREG */
368         switch (cmd) {
369         case SIOCGMIIPHY:
370                 if (mdio->prtad == MDIO_PRTAD_NONE)
371                         return -EOPNOTSUPP;
372                 mii_data->phy_id = mdio->prtad;
373                 cmd = SIOCGMIIREG;
374                 break;
375         case SIOCGMIIREG:
376                 break;
377         case SIOCSMIIREG:
378                 if (!capable(CAP_NET_ADMIN))
379                         return -EPERM;
380                 break;
381         default:
382                 return -EOPNOTSUPP;
383         }
384
385         /* Validate/convert phy_id */
386         if ((mdio->mode_support & MDIO_SUPPORTS_C45) &&
387             mdio_phy_id_is_c45(mii_data->phy_id)) {
388                 prtad = mdio_phy_id_prtad(mii_data->phy_id);
389                 devad = mdio_phy_id_devad(mii_data->phy_id);
390         } else if ((mdio->mode_support & MDIO_SUPPORTS_C22) &&
391                    mii_data->phy_id < 0x20) {
392                 prtad = mii_data->phy_id;
393                 devad = MDIO_DEVAD_NONE;
394                 addr &= 0x1f;
395         } else if ((mdio->mode_support & MDIO_EMULATE_C22) &&
396                    mdio->prtad != MDIO_PRTAD_NONE &&
397                    mii_data->phy_id == mdio->prtad) {
398                 /* Remap commonly-used MII registers. */
399                 prtad = mdio->prtad;
400                 switch (addr) {
401                 case MII_BMCR:
402                 case MII_BMSR:
403                 case MII_PHYSID1:
404                 case MII_PHYSID2:
405                         devad = __ffs(mdio->mmds);
406                         break;
407                 case MII_ADVERTISE:
408                 case MII_LPA:
409                         if (!(mdio->mmds & MDIO_DEVS_AN))
410                                 return -EINVAL;
411                         devad = MDIO_MMD_AN;
412                         if (addr == MII_ADVERTISE)
413                                 addr = MDIO_AN_ADVERTISE;
414                         else
415                                 addr = MDIO_AN_LPA;
416                         break;
417                 default:
418                         return -EINVAL;
419                 }
420         } else {
421                 return -EINVAL;
422         }
423
424         if (cmd == SIOCGMIIREG) {
425                 int rc = mdio->mdio_read(mdio->dev, prtad, devad, addr);
426                 if (rc < 0)
427                         return rc;
428                 mii_data->val_out = rc;
429                 return 0;
430         } else {
431                 return mdio->mdio_write(mdio->dev, prtad, devad, addr,
432                                         mii_data->val_in);
433         }
434 }
435 EXPORT_SYMBOL(mdio_mii_ioctl);