Deleted Added
full compact
cxgb_vsc8211.c (171978) cxgb_vsc8211.c (176472)
1/**************************************************************************
2
3Copyright (c) 2007, Chelsio Inc.
4All rights reserved.
5
6Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are met:
8

--- 14 unchanged lines hidden (view full) ---

23INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26POSSIBILITY OF SUCH DAMAGE.
27
28***************************************************************************/
29
30#include <sys/cdefs.h>
1/**************************************************************************
2
3Copyright (c) 2007, Chelsio Inc.
4All rights reserved.
5
6Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are met:
8

--- 14 unchanged lines hidden (view full) ---

23INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26POSSIBILITY OF SUCH DAMAGE.
27
28***************************************************************************/
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: head/sys/dev/cxgb/common/cxgb_vsc8211.c 171978 2007-08-25 21:07:37Z kmacy $");
31__FBSDID("$FreeBSD: head/sys/dev/cxgb/common/cxgb_vsc8211.c 176472 2008-02-23 01:06:17Z kmacy $");
32
33#ifdef CONFIG_DEFINED
34#include <cxgb_include.h>
35#else
36#include <dev/cxgb/cxgb_include.h>
37#endif
38
32
33#ifdef CONFIG_DEFINED
34#include <cxgb_include.h>
35#else
36#include <dev/cxgb/cxgb_include.h>
37#endif
38
39#undef msleep
40#define msleep t3_os_sleep
41
39/* VSC8211 PHY specific registers. */
40enum {
42/* VSC8211 PHY specific registers. */
43enum {
44 VSC8211_SIGDET_CTRL = 19,
45 VSC8211_EXT_CTRL = 23,
41 VSC8211_INTR_ENABLE = 25,
42 VSC8211_INTR_STATUS = 26,
43 VSC8211_AUX_CTRL_STAT = 28,
46 VSC8211_INTR_ENABLE = 25,
47 VSC8211_INTR_STATUS = 26,
48 VSC8211_AUX_CTRL_STAT = 28,
49 VSC8211_EXT_PAGE_AXS = 31,
44};
45
46enum {
47 VSC_INTR_RX_ERR = 1 << 0,
48 VSC_INTR_MS_ERR = 1 << 1, /* master/slave resolution error */
49 VSC_INTR_CABLE = 1 << 2, /* cable impairment */
50 VSC_INTR_FALSE_CARR = 1 << 3, /* false carrier */
51 VSC_INTR_MEDIA_CHG = 1 << 4, /* AMS media change */
52 VSC_INTR_RX_FIFO = 1 << 5, /* Rx FIFO over/underflow */
53 VSC_INTR_TX_FIFO = 1 << 6, /* Tx FIFO over/underflow */
54 VSC_INTR_DESCRAMBL = 1 << 7, /* descrambler lock-lost */
55 VSC_INTR_SYMBOL_ERR = 1 << 8, /* symbol error */
56 VSC_INTR_NEG_DONE = 1 << 10, /* autoneg done */
57 VSC_INTR_NEG_ERR = 1 << 11, /* autoneg error */
50};
51
52enum {
53 VSC_INTR_RX_ERR = 1 << 0,
54 VSC_INTR_MS_ERR = 1 << 1, /* master/slave resolution error */
55 VSC_INTR_CABLE = 1 << 2, /* cable impairment */
56 VSC_INTR_FALSE_CARR = 1 << 3, /* false carrier */
57 VSC_INTR_MEDIA_CHG = 1 << 4, /* AMS media change */
58 VSC_INTR_RX_FIFO = 1 << 5, /* Rx FIFO over/underflow */
59 VSC_INTR_TX_FIFO = 1 << 6, /* Tx FIFO over/underflow */
60 VSC_INTR_DESCRAMBL = 1 << 7, /* descrambler lock-lost */
61 VSC_INTR_SYMBOL_ERR = 1 << 8, /* symbol error */
62 VSC_INTR_NEG_DONE = 1 << 10, /* autoneg done */
63 VSC_INTR_NEG_ERR = 1 << 11, /* autoneg error */
64 VSC_INTR_DPLX_CHG = 1 << 12, /* duplex change */
58 VSC_INTR_LINK_CHG = 1 << 13, /* link change */
65 VSC_INTR_LINK_CHG = 1 << 13, /* link change */
66 VSC_INTR_SPD_CHG = 1 << 14, /* speed change */
59 VSC_INTR_ENABLE = 1 << 15, /* interrupt enable */
60};
61
67 VSC_INTR_ENABLE = 1 << 15, /* interrupt enable */
68};
69
70enum {
71 VSC_CTRL_CLAUSE37_VIEW = 1 << 4, /* Switch to Clause 37 view */
72 VSC_CTRL_MEDIA_MODE_HI = 0xf000 /* High part of media mode select */
73};
74
62#define CFG_CHG_INTR_MASK (VSC_INTR_LINK_CHG | VSC_INTR_NEG_ERR | \
75#define CFG_CHG_INTR_MASK (VSC_INTR_LINK_CHG | VSC_INTR_NEG_ERR | \
76 VSC_INTR_DPLX_CHG | VSC_INTR_SPD_CHG | \
63 VSC_INTR_NEG_DONE)
64#define INTR_MASK (CFG_CHG_INTR_MASK | VSC_INTR_TX_FIFO | VSC_INTR_RX_FIFO | \
65 VSC_INTR_ENABLE)
66
67/* PHY specific auxiliary control & status register fields */
68#define S_ACSR_ACTIPHY_TMR 0
69#define M_ACSR_ACTIPHY_TMR 0x3
70#define V_ACSR_ACTIPHY_TMR(x) ((x) << S_ACSR_ACTIPHY_TMR)

--- 113 unchanged lines hidden (view full) ---

184 *speed = sp;
185 if (duplex)
186 *duplex = dplx;
187 if (fc)
188 *fc = pause;
189 return 0;
190}
191
77 VSC_INTR_NEG_DONE)
78#define INTR_MASK (CFG_CHG_INTR_MASK | VSC_INTR_TX_FIFO | VSC_INTR_RX_FIFO | \
79 VSC_INTR_ENABLE)
80
81/* PHY specific auxiliary control & status register fields */
82#define S_ACSR_ACTIPHY_TMR 0
83#define M_ACSR_ACTIPHY_TMR 0x3
84#define V_ACSR_ACTIPHY_TMR(x) ((x) << S_ACSR_ACTIPHY_TMR)

--- 113 unchanged lines hidden (view full) ---

198 *speed = sp;
199 if (duplex)
200 *duplex = dplx;
201 if (fc)
202 *fc = pause;
203 return 0;
204}
205
206static int vsc8211_get_link_status_fiber(struct cphy *cphy, int *link_ok,
207 int *speed, int *duplex, int *fc)
208{
209 unsigned int bmcr, status, lpa, adv;
210 int err, sp = -1, dplx = -1, pause = 0;
211
212 err = mdio_read(cphy, 0, MII_BMCR, &bmcr);
213 if (!err)
214 err = mdio_read(cphy, 0, MII_BMSR, &status);
215 if (err)
216 return err;
217
218 if (link_ok) {
219 /*
220 * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it
221 * once more to get the current link state.
222 */
223 if (!(status & BMSR_LSTATUS))
224 err = mdio_read(cphy, 0, MII_BMSR, &status);
225 if (err)
226 return err;
227 *link_ok = (status & BMSR_LSTATUS) != 0;
228 }
229 if (!(bmcr & BMCR_ANENABLE)) {
230 dplx = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
231 if (bmcr & BMCR_SPEED1000)
232 sp = SPEED_1000;
233 else if (bmcr & BMCR_SPEED100)
234 sp = SPEED_100;
235 else
236 sp = SPEED_10;
237 } else if (status & BMSR_ANEGCOMPLETE) {
238 err = mdio_read(cphy, 0, MII_LPA, &lpa);
239 if (!err)
240 err = mdio_read(cphy, 0, MII_ADVERTISE, &adv);
241 if (err)
242 return err;
243
244 if (adv & lpa & ADVERTISE_1000XFULL) {
245 dplx = DUPLEX_FULL;
246 sp = SPEED_1000;
247 } else if (adv & lpa & ADVERTISE_1000XHALF) {
248 dplx = DUPLEX_HALF;
249 sp = SPEED_1000;
250 }
251
252 if (fc && dplx == DUPLEX_FULL) {
253 if (lpa & adv & ADVERTISE_1000XPAUSE)
254 pause = PAUSE_RX | PAUSE_TX;
255 else if ((lpa & ADVERTISE_1000XPAUSE) &&
256 (adv & lpa & ADVERTISE_1000XPSE_ASYM))
257 pause = PAUSE_TX;
258 else if ((lpa & ADVERTISE_1000XPSE_ASYM) &&
259 (adv & ADVERTISE_1000XPAUSE))
260 pause = PAUSE_RX;
261 }
262 }
263 if (speed)
264 *speed = sp;
265 if (duplex)
266 *duplex = dplx;
267 if (fc)
268 *fc = pause;
269 return 0;
270}
271
272/*
273 * Enable/disable auto MDI/MDI-X in forced link speed mode.
274 */
275static int vsc8211_set_automdi(struct cphy *phy, int enable)
276{
277 int err;
278
279 if ((err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0x52b5)) != 0 ||
280 (err = mdio_write(phy, 0, 18, 0x12)) != 0 ||
281 (err = mdio_write(phy, 0, 17, enable ? 0x2803 : 0x3003)) != 0 ||
282 (err = mdio_write(phy, 0, 16, 0x87fa)) != 0 ||
283 (err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0)) != 0)
284 return err;
285 return 0;
286}
287
288static int vsc8211_set_speed_duplex(struct cphy *phy, int speed, int duplex)
289{
290 int err;
291
292 err = t3_set_phy_speed_duplex(phy, speed, duplex);
293 if (!err)
294 err = vsc8211_set_automdi(phy, 1);
295 return err;
296}
297
192static int vsc8211_power_down(struct cphy *cphy, int enable)
193{
194 return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN,
195 enable ? BMCR_PDOWN : 0);
196}
197
198static int vsc8211_intr_handler(struct cphy *cphy)
199{

--- 9 unchanged lines hidden (view full) ---

209 cphy_cause |= cphy_cause_link_change;
210 if (cause & (VSC_INTR_RX_FIFO | VSC_INTR_TX_FIFO))
211 cphy_cause |= cphy_cause_fifo_error;
212 return cphy_cause;
213}
214
215#ifdef C99_NOT_SUPPORTED
216static struct cphy_ops vsc8211_ops = {
298static int vsc8211_power_down(struct cphy *cphy, int enable)
299{
300 return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN,
301 enable ? BMCR_PDOWN : 0);
302}
303
304static int vsc8211_intr_handler(struct cphy *cphy)
305{

--- 9 unchanged lines hidden (view full) ---

315 cphy_cause |= cphy_cause_link_change;
316 if (cause & (VSC_INTR_RX_FIFO | VSC_INTR_TX_FIFO))
317 cphy_cause |= cphy_cause_fifo_error;
318 return cphy_cause;
319}
320
321#ifdef C99_NOT_SUPPORTED
322static struct cphy_ops vsc8211_ops = {
217 NULL,
218 vsc8211_reset,
219 vsc8211_intr_enable,
220 vsc8211_intr_disable,
221 vsc8211_intr_clear,
222 vsc8211_intr_handler,
223 vsc8211_autoneg_enable,
224 vsc8211_autoneg_restart,
225 t3_phy_advertise,
226 NULL,
323 vsc8211_reset,
324 vsc8211_intr_enable,
325 vsc8211_intr_disable,
326 vsc8211_intr_clear,
327 vsc8211_intr_handler,
328 vsc8211_autoneg_enable,
329 vsc8211_autoneg_restart,
330 t3_phy_advertise,
331 NULL,
227 t3_set_phy_speed_duplex,
332 vsc8211_set_speed_duplex,
228 vsc8211_get_link_status,
229 vsc8211_power_down,
230};
333 vsc8211_get_link_status,
334 vsc8211_power_down,
335};
336
337static struct cphy_ops vsc8211_fiber_ops = {
338 vsc8211_reset,
339 vsc8211_intr_enable,
340 vsc8211_intr_disable,
341 vsc8211_intr_clear,
342 vsc8211_intr_handler,
343 vsc8211_autoneg_enable,
344 vsc8211_autoneg_restart,
345 t3_phy_advertise_fiber,
346 NULL,
347 t3_set_phy_speed_duplex,
348 vsc8211_get_link_status_fiber,
349 vsc8211_power_down,
350};
231#else
232static struct cphy_ops vsc8211_ops = {
233 .reset = vsc8211_reset,
234 .intr_enable = vsc8211_intr_enable,
235 .intr_disable = vsc8211_intr_disable,
236 .intr_clear = vsc8211_intr_clear,
237 .intr_handler = vsc8211_intr_handler,
238 .autoneg_enable = vsc8211_autoneg_enable,
239 .autoneg_restart = vsc8211_autoneg_restart,
240 .advertise = t3_phy_advertise,
351#else
352static struct cphy_ops vsc8211_ops = {
353 .reset = vsc8211_reset,
354 .intr_enable = vsc8211_intr_enable,
355 .intr_disable = vsc8211_intr_disable,
356 .intr_clear = vsc8211_intr_clear,
357 .intr_handler = vsc8211_intr_handler,
358 .autoneg_enable = vsc8211_autoneg_enable,
359 .autoneg_restart = vsc8211_autoneg_restart,
360 .advertise = t3_phy_advertise,
241 .set_speed_duplex = t3_set_phy_speed_duplex,
361 .set_speed_duplex = vsc8211_set_speed_duplex,
242 .get_link_status = vsc8211_get_link_status,
243 .power_down = vsc8211_power_down,
244};
362 .get_link_status = vsc8211_get_link_status,
363 .power_down = vsc8211_power_down,
364};
365
366static struct cphy_ops vsc8211_fiber_ops = {
367 .reset = vsc8211_reset,
368 .intr_enable = vsc8211_intr_enable,
369 .intr_disable = vsc8211_intr_disable,
370 .intr_clear = vsc8211_intr_clear,
371 .intr_handler = vsc8211_intr_handler,
372 .autoneg_enable = vsc8211_autoneg_enable,
373 .autoneg_restart = vsc8211_autoneg_restart,
374 .advertise = t3_phy_advertise_fiber,
375 .set_speed_duplex = t3_set_phy_speed_duplex,
376 .get_link_status = vsc8211_get_link_status_fiber,
377 .power_down = vsc8211_power_down,
378};
245#endif
246
379#endif
380
247void t3_vsc8211_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
248 const struct mdio_ops *mdio_ops)
381int t3_vsc8211_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
382 const struct mdio_ops *mdio_ops)
249{
383{
250 cphy_init(phy, adapter, phy_addr, &vsc8211_ops, mdio_ops);
251 t3_os_sleep(20); /* PHY needs ~10ms to start responding to MDIO */
384 int err;
385 unsigned int val;
386
387 cphy_init(phy, adapter, phy_addr, &vsc8211_ops, mdio_ops,
388 SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Full |
389 SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_MII |
390 SUPPORTED_TP | SUPPORTED_IRQ, "10/100/1000BASE-T");
391 msleep(20); /* PHY needs ~10ms to start responding to MDIO */
392
393 err = mdio_read(phy, 0, VSC8211_EXT_CTRL, &val);
394 if (err)
395 return err;
396 if (val & VSC_CTRL_MEDIA_MODE_HI)
397 return 0; /* copper interface, done */
398
399 phy->caps = SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg |
400 SUPPORTED_MII | SUPPORTED_FIBRE | SUPPORTED_IRQ;
401 phy->desc = "1000BASE-X";
402 phy->ops = &vsc8211_fiber_ops;
403
404 if ((err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 1)) != 0 ||
405 (err = mdio_write(phy, 0, VSC8211_SIGDET_CTRL, 1)) != 0 ||
406 (err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0)) != 0 ||
407 (err = mdio_write(phy, 0, VSC8211_EXT_CTRL,
408 val | VSC_CTRL_CLAUSE37_VIEW)) != 0 ||
409 (err = vsc8211_reset(phy, 0)) != 0)
410 return err;
411
412 udelay(5); /* delay after reset before next SMI */
413 return 0;
252}
414}