Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[linux-2.6] / drivers / net / sfc / mdio_10g.c
1 /****************************************************************************
2  * Driver for Solarflare Solarstorm network controllers and boards
3  * Copyright 2006-2008 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 "boards.h"
18
19 int mdio_clause45_reset_mmd(struct efx_nic *port, int mmd,
20                             int spins, int spintime)
21 {
22         u32 ctrl;
23         int phy_id = port->mii.phy_id;
24
25         /* Catch callers passing values in the wrong units (or just silly) */
26         EFX_BUG_ON_PARANOID(spins * spintime >= 5000);
27
28         mdio_clause45_write(port, phy_id, mmd, MDIO_MMDREG_CTRL1,
29                             (1 << MDIO_MMDREG_CTRL1_RESET_LBN));
30         /* Wait for the reset bit to clear. */
31         do {
32                 msleep(spintime);
33                 ctrl = mdio_clause45_read(port, phy_id, mmd, MDIO_MMDREG_CTRL1);
34                 spins--;
35
36         } while (spins && (ctrl & (1 << MDIO_MMDREG_CTRL1_RESET_LBN)));
37
38         return spins ? spins : -ETIMEDOUT;
39 }
40
41 static int mdio_clause45_check_mmd(struct efx_nic *efx, int mmd,
42                                    int fault_fatal)
43 {
44         int status;
45         int phy_id = efx->mii.phy_id;
46
47         /* Read MMD STATUS2 to check it is responding. */
48         status = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_STAT2);
49         if (((status >> MDIO_MMDREG_STAT2_PRESENT_LBN) &
50              ((1 << MDIO_MMDREG_STAT2_PRESENT_WIDTH) - 1)) !=
51             MDIO_MMDREG_STAT2_PRESENT_VAL) {
52                 EFX_ERR(efx, "PHY MMD %d not responding.\n", mmd);
53                 return -EIO;
54         }
55
56         /* Read MMD STATUS 1 to check for fault. */
57         status = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_STAT1);
58         if ((status & (1 << MDIO_MMDREG_STAT1_FAULT_LBN)) != 0) {
59                 if (fault_fatal) {
60                         EFX_ERR(efx, "PHY MMD %d reporting fatal"
61                                 " fault: status %x\n", mmd, status);
62                         return -EIO;
63                 } else {
64                         EFX_LOG(efx, "PHY MMD %d reporting status"
65                                 " %x (expected)\n", mmd, status);
66                 }
67         }
68         return 0;
69 }
70
71 /* This ought to be ridiculous overkill. We expect it to fail rarely */
72 #define MDIO45_RESET_TIME       1000 /* ms */
73 #define MDIO45_RESET_ITERS      100
74
75 int mdio_clause45_wait_reset_mmds(struct efx_nic *efx,
76                                   unsigned int mmd_mask)
77 {
78         const int spintime = MDIO45_RESET_TIME / MDIO45_RESET_ITERS;
79         int tries = MDIO45_RESET_ITERS;
80         int rc = 0;
81         int in_reset;
82
83         while (tries) {
84                 int mask = mmd_mask;
85                 int mmd = 0;
86                 int stat;
87                 in_reset = 0;
88                 while (mask) {
89                         if (mask & 1) {
90                                 stat = mdio_clause45_read(efx,
91                                                           efx->mii.phy_id,
92                                                           mmd,
93                                                           MDIO_MMDREG_CTRL1);
94                                 if (stat < 0) {
95                                         EFX_ERR(efx, "failed to read status of"
96                                                 " MMD %d\n", mmd);
97                                         return -EIO;
98                                 }
99                                 if (stat & (1 << MDIO_MMDREG_CTRL1_RESET_LBN))
100                                         in_reset |= (1 << mmd);
101                         }
102                         mask = mask >> 1;
103                         mmd++;
104                 }
105                 if (!in_reset)
106                         break;
107                 tries--;
108                 msleep(spintime);
109         }
110         if (in_reset != 0) {
111                 EFX_ERR(efx, "not all MMDs came out of reset in time."
112                         " MMDs still in reset: %x\n", in_reset);
113                 rc = -ETIMEDOUT;
114         }
115         return rc;
116 }
117
118 int mdio_clause45_check_mmds(struct efx_nic *efx,
119                              unsigned int mmd_mask, unsigned int fatal_mask)
120 {
121         int devices, mmd = 0;
122         int probe_mmd;
123
124         /* Historically we have probed the PHYXS to find out what devices are
125          * present,but that doesn't work so well if the PHYXS isn't expected
126          * to exist, if so just find the first item in the list supplied. */
127         probe_mmd = (mmd_mask & MDIO_MMDREG_DEVS0_PHYXS) ? MDIO_MMD_PHYXS :
128             __ffs(mmd_mask);
129         devices = mdio_clause45_read(efx, efx->mii.phy_id,
130                                      probe_mmd, MDIO_MMDREG_DEVS0);
131
132         /* Check all the expected MMDs are present */
133         if (devices < 0) {
134                 EFX_ERR(efx, "failed to read devices present\n");
135                 return -EIO;
136         }
137         if ((devices & mmd_mask) != mmd_mask) {
138                 EFX_ERR(efx, "required MMDs not present: got %x, "
139                         "wanted %x\n", devices, mmd_mask);
140                 return -ENODEV;
141         }
142         EFX_TRACE(efx, "Devices present: %x\n", devices);
143
144         /* Check all required MMDs are responding and happy. */
145         while (mmd_mask) {
146                 if (mmd_mask & 1) {
147                         int fault_fatal = fatal_mask & 1;
148                         if (mdio_clause45_check_mmd(efx, mmd, fault_fatal))
149                                 return -EIO;
150                 }
151                 mmd_mask = mmd_mask >> 1;
152                 fatal_mask = fatal_mask >> 1;
153                 mmd++;
154         }
155
156         return 0;
157 }
158
159 int mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
160 {
161         int phy_id = efx->mii.phy_id;
162         int status;
163         int ok = 1;
164         int mmd = 0;
165         int good;
166
167         while (mmd_mask) {
168                 if (mmd_mask & 1) {
169                         /* Double reads because link state is latched, and a
170                          * read moves the current state into the register */
171                         status = mdio_clause45_read(efx, phy_id,
172                                                     mmd, MDIO_MMDREG_STAT1);
173                         status = mdio_clause45_read(efx, phy_id,
174                                                     mmd, MDIO_MMDREG_STAT1);
175
176                         good = status & (1 << MDIO_MMDREG_STAT1_LINK_LBN);
177                         ok = ok && good;
178                 }
179                 mmd_mask = (mmd_mask >> 1);
180                 mmd++;
181         }
182         return ok;
183 }
184
185 /**
186  * mdio_clause45_get_settings - Read (some of) the PHY settings over MDIO.
187  * @efx:                Efx NIC
188  * @ecmd:               Buffer for settings
189  *
190  * On return the 'port', 'speed', 'supported' and 'advertising' fields of
191  * ecmd have been filled out based on the PMA type.
192  */
193 void mdio_clause45_get_settings(struct efx_nic *efx,
194                                 struct ethtool_cmd *ecmd)
195 {
196         int pma_type;
197
198         /* If no PMA is present we are presumably talking something XAUI-ish
199          * like CX4. Which we report as FIBRE (see below) */
200         if ((efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_PMAPMD)) == 0) {
201                 ecmd->speed = SPEED_10000;
202                 ecmd->port = PORT_FIBRE;
203                 ecmd->supported = SUPPORTED_FIBRE;
204                 ecmd->advertising = ADVERTISED_FIBRE;
205                 return;
206         }
207
208         pma_type = mdio_clause45_read(efx, efx->mii.phy_id,
209                                       MDIO_MMD_PMAPMD, MDIO_MMDREG_CTRL2);
210         pma_type &= MDIO_PMAPMD_CTRL2_TYPE_MASK;
211
212         switch (pma_type) {
213                 /* We represent CX4 as fibre in the absence of anything
214                    better. */
215         case MDIO_PMAPMD_CTRL2_10G_CX4:
216                 ecmd->speed = SPEED_10000;
217                 ecmd->port = PORT_FIBRE;
218                 ecmd->supported = SUPPORTED_FIBRE;
219                 ecmd->advertising = ADVERTISED_FIBRE;
220                 break;
221                 /* 10G Base-T */
222         case MDIO_PMAPMD_CTRL2_10G_BT:
223                 ecmd->speed = SPEED_10000;
224                 ecmd->port = PORT_TP;
225                 ecmd->supported = SUPPORTED_TP | SUPPORTED_10000baseT_Full;
226                 ecmd->advertising = (ADVERTISED_FIBRE
227                                      | ADVERTISED_10000baseT_Full);
228                 break;
229         case MDIO_PMAPMD_CTRL2_1G_BT:
230                 ecmd->speed = SPEED_1000;
231                 ecmd->port = PORT_TP;
232                 ecmd->supported = SUPPORTED_TP | SUPPORTED_1000baseT_Full;
233                 ecmd->advertising = (ADVERTISED_FIBRE
234                                      | ADVERTISED_1000baseT_Full);
235                 break;
236         case MDIO_PMAPMD_CTRL2_100_BT:
237                 ecmd->speed = SPEED_100;
238                 ecmd->port = PORT_TP;
239                 ecmd->supported = SUPPORTED_TP | SUPPORTED_100baseT_Full;
240                 ecmd->advertising = (ADVERTISED_FIBRE
241                                      | ADVERTISED_100baseT_Full);
242                 break;
243         case MDIO_PMAPMD_CTRL2_10_BT:
244                 ecmd->speed = SPEED_10;
245                 ecmd->port = PORT_TP;
246                 ecmd->supported = SUPPORTED_TP | SUPPORTED_10baseT_Full;
247                 ecmd->advertising = ADVERTISED_FIBRE | ADVERTISED_10baseT_Full;
248                 break;
249         /* All the other defined modes are flavours of
250          * 10G optical */
251         default:
252                 ecmd->speed = SPEED_10000;
253                 ecmd->port = PORT_FIBRE;
254                 ecmd->supported = SUPPORTED_FIBRE;
255                 ecmd->advertising = ADVERTISED_FIBRE;
256                 break;
257         }
258 }
259
260 /**
261  * mdio_clause45_set_settings - Set (some of) the PHY settings over MDIO.
262  * @efx:                Efx NIC
263  * @ecmd:               New settings
264  *
265  * Currently this just enforces that we are _not_ changing the
266  * 'port', 'speed', 'supported' or 'advertising' settings as these
267  * cannot be changed on any currently supported PHY.
268  */
269 int mdio_clause45_set_settings(struct efx_nic *efx,
270                                struct ethtool_cmd *ecmd)
271 {
272         struct ethtool_cmd tmpcmd;
273         mdio_clause45_get_settings(efx, &tmpcmd);
274         /* None of the current PHYs support more than one mode
275          * of operation (and only 10GBT ever will), so keep things
276          * simple for now */
277         if ((ecmd->speed == tmpcmd.speed) && (ecmd->port == tmpcmd.port) &&
278             (ecmd->supported == tmpcmd.supported) &&
279             (ecmd->advertising == tmpcmd.advertising))
280                 return 0;
281         return -EOPNOTSUPP;
282 }