1 /**************************************************************************
2
3 Copyright (c) 2009 Chelsio Inc.
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8
9 1. Redistributions of source code must retain the above copyright notice,
10 this list of conditions and the following disclaimer.
11
12 2. Neither the name of the Chelsio Corporation nor the names of its
13 contributors may be used to endorse or promote products derived from
14 this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 POSSIBILITY OF SUCH DAMAGE.
27
28 ***************************************************************************/
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD: releng/8.1/sys/dev/cxgb/common/cxgb_aq100x.c 200175 2009-12-06 01:45:55Z np $");
32
33 #include <cxgb_include.h>
34
35 #undef msleep
36 #define msleep t3_os_sleep
37
38 enum {
39 /* MDIO_DEV_PMA_PMD registers */
40 AQ_LINK_STAT = 0xe800,
41
42 /* MDIO_DEV_XGXS registers */
43 AQ_XAUI_RX_CFG = 0xc400,
44 AQ_XAUI_KX_CFG = 0xc440,
45 AQ_XAUI_TX_CFG = 0xe400,
46
47 /* MDIO_DEV_ANEG registers */
48 AQ_100M_CTRL = 0x0010,
49 AQ_10G_CTRL = 0x0020,
50 AQ_1G_CTRL = 0xc400,
51 AQ_ANEG_STAT = 0xc800,
52
53 /* MDIO_DEV_VEND1 registers */
54 AQ_FW_VERSION = 0x0020,
55 AQ_THERMAL_THR = 0xc421,
56 AQ_THERMAL1 = 0xc820,
57 AQ_THERMAL2 = 0xc821,
58 AQ_IFLAG_GLOBAL = 0xfc00,
59 AQ_IMASK_GLOBAL = 0xff00,
60 };
61
62 #define AQBIT(x) (1 << (0x##x))
63 #define ADV_1G_FULL AQBIT(f)
64 #define ADV_1G_HALF AQBIT(e)
65 #define ADV_10G_FULL AQBIT(c)
66
67 #define AQ_WRITE_REGS(phy, regs) do { \
68 int i; \
69 for (i = 0; i < ARRAY_SIZE(regs); i++) { \
70 (void) mdio_write(phy, regs[i].mmd, regs[i].reg, regs[i].val); \
71 } \
72 } while (0)
73 #define AQ_READ_REGS(phy, regs) do { \
74 unsigned i, v; \
75 for (i = 0; i < ARRAY_SIZE(regs); i++) { \
76 (void) mdio_read(phy, regs[i].mmd, regs[i].reg, &v); \
77 } \
78 } while (0)
79
80 /*
81 * Return value is temperature in celcius, 0xffff for error or don't know.
82 */
83 static int
84 aq100x_temperature(struct cphy *phy)
85 {
86 unsigned int v;
87
88 if (mdio_read(phy, MDIO_DEV_VEND1, AQ_THERMAL2, &v) ||
89 v == 0xffff || (v & 1) != 1)
90 return (0xffff);
91
92 if (mdio_read(phy, MDIO_DEV_VEND1, AQ_THERMAL1, &v))
93 return (0xffff);
94
95 return ((int)((signed char)(v >> 8)));
96 }
97
98 static int
99 aq100x_set_defaults(struct cphy *phy)
100 {
101 return mdio_write(phy, MDIO_DEV_VEND1, AQ_THERMAL_THR, 0x6c00);
102 }
103
104 static int
105 aq100x_reset(struct cphy *phy, int wait)
106 {
107 int err;
108 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
109 if (!err)
110 err = aq100x_set_defaults(phy);
111 return (err);
112 }
113
114 static int
115 aq100x_intr_enable(struct cphy *phy)
116 {
117 struct {
118 int mmd;
119 int reg;
120 int val;
121 } imasks[] = {
122 {MDIO_DEV_VEND1, 0xd400, AQBIT(e)},
123 {MDIO_DEV_VEND1, 0xff01, AQBIT(2)},
124 {MDIO_DEV_VEND1, AQ_IMASK_GLOBAL, AQBIT(0)}
125 };
126
127 AQ_WRITE_REGS(phy, imasks);
128
129 return (0);
130 }
131
132 static int
133 aq100x_intr_disable(struct cphy *phy)
134 {
135 struct {
136 int mmd;
137 int reg;
138 int val;
139 } imasks[] = {
140 {MDIO_DEV_VEND1, 0xd400, 0},
141 {MDIO_DEV_VEND1, 0xff01, 0},
142 {MDIO_DEV_VEND1, AQ_IMASK_GLOBAL, 0}
143 };
144
145 AQ_WRITE_REGS(phy, imasks);
146
147 return (0);
148 }
149
150 static int
151 aq100x_intr_clear(struct cphy *phy)
152 {
153 struct {
154 int mmd;
155 int reg;
156 } iclr[] = {
157 {MDIO_DEV_VEND1, 0xcc00},
158 {MDIO_DEV_VEND1, AQ_IMASK_GLOBAL} /* needed? */
159 };
160
161 AQ_READ_REGS(phy, iclr);
162
163 return (0);
164 }
165
166 static int
167 aq100x_vendor_intr(struct cphy *phy, int *rc)
168 {
169 int err;
170 unsigned int cause, v;
171
172 err = mdio_read(phy, MDIO_DEV_VEND1, 0xfc01, &cause);
173 if (err)
174 return (err);
175
176 if (cause & AQBIT(2)) {
177 err = mdio_read(phy, MDIO_DEV_VEND1, 0xcc00, &v);
178 if (err)
179 return (err);
180
181 if (v & AQBIT(e)) {
182 CH_WARN(phy->adapter, "PHY%d: temperature is now %dC\n",
183 phy->addr, aq100x_temperature(phy));
184
185 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN,
186 phy->addr ? F_GPIO10_OUT_VAL : F_GPIO6_OUT_VAL, 0);
187
188 *rc |= cphy_cause_alarm;
189 }
190
191 cause &= ~4;
192 }
193
194 if (cause)
195 CH_WARN(phy->adapter, "PHY%d: unhandled vendor interrupt"
196 " (0x%x)\n", phy->addr, cause);
197
198 return (0);
199
200 }
201
202 static int
203 aq100x_intr_handler(struct cphy *phy)
204 {
205 int err, rc = 0;
206 unsigned int cause;
207
208 err = mdio_read(phy, MDIO_DEV_VEND1, AQ_IFLAG_GLOBAL, &cause);
209 if (err)
210 return (err);
211
212 if (cause & AQBIT(0)) {
213 err = aq100x_vendor_intr(phy, &rc);
214 if (err)
215 return (err);
216 cause &= ~AQBIT(0);
217 }
218
219 if (cause)
220 CH_WARN(phy->adapter, "PHY%d: unhandled interrupt (0x%x)\n",
221 phy->addr, cause);
222
223 return (rc);
224 }
225
226 static int
227 aq100x_power_down(struct cphy *phy, int off)
228 {
229 int err, wait = 500;
230 unsigned int v;
231
232 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, BMCR_PDOWN,
233 off ? BMCR_PDOWN : 0);
234 if (err || off)
235 return (v);
236
237 msleep(300);
238 do {
239 err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v);
240 if (err)
241 return (err);
242 v &= BMCR_RESET;
243 if (v)
244 msleep(10);
245 } while (v && --wait);
246 if (v) {
247 CH_WARN(phy->adapter, "PHY%d: power-up timed out (0x%x).\n",
248 phy->addr, v);
249 return (ETIMEDOUT);
250 }
251
252 return (0);
253 }
254
255 static int
256 aq100x_autoneg_enable(struct cphy *phy)
257 {
258 int err;
259
260 err = aq100x_power_down(phy, 0);
261 if (!err)
262 err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, MII_BMCR,
263 BMCR_RESET, BMCR_ANENABLE | BMCR_ANRESTART);
264
265 return (err);
266 }
267
268 static int
269 aq100x_autoneg_restart(struct cphy *phy)
270 {
271 return aq100x_autoneg_enable(phy);
272 }
273
274 static int
275 aq100x_advertise(struct cphy *phy, unsigned int advertise_map)
276 {
277 unsigned int adv;
278 int err;
279
280 /* 10G advertisement */
281 adv = 0;
282 if (advertise_map & ADVERTISED_10000baseT_Full)
283 adv |= ADV_10G_FULL;
284 err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, AQ_10G_CTRL,
285 ADV_10G_FULL, adv);
286 if (err)
287 return (err);
288
289 /* 1G advertisement */
290 adv = 0;
291 if (advertise_map & ADVERTISED_1000baseT_Full)
292 adv |= ADV_1G_FULL;
293 if (advertise_map & ADVERTISED_1000baseT_Half)
294 adv |= ADV_1G_HALF;
295 err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, AQ_1G_CTRL,
296 ADV_1G_FULL | ADV_1G_HALF, adv);
297 if (err)
298 return (err);
299
300 /* 100M, pause advertisement */
301 adv = 0;
302 if (advertise_map & ADVERTISED_100baseT_Half)
303 adv |= ADVERTISE_100HALF;
304 if (advertise_map & ADVERTISED_100baseT_Full)
305 adv |= ADVERTISE_100FULL;
306 if (advertise_map & ADVERTISED_Pause)
307 adv |= ADVERTISE_PAUSE_CAP;
308 if (advertise_map & ADVERTISED_Asym_Pause)
309 adv |= ADVERTISE_PAUSE_ASYM;
310 err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, AQ_100M_CTRL, 0xfe0, adv);
311
312 return (err);
313 }
314
315 static int
316 aq100x_set_loopback(struct cphy *phy, int mmd, int dir, int enable)
317 {
318 return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
319 BMCR_LOOPBACK, enable ? BMCR_LOOPBACK : 0);
320 }
321
322 static int
323 aq100x_set_speed_duplex(struct cphy *phy, int speed, int duplex)
324 {
325 int err, set;
326
327 if (speed == SPEED_100)
328 set = BMCR_SPEED100;
329 else if (speed == SPEED_1000)
330 set = BMCR_SPEED1000;
331 else if (speed == SPEED_10000)
332 set = BMCR_SPEED1000 | BMCR_SPEED100;
333 else
334 return (EINVAL);
335
336 if (duplex != DUPLEX_FULL)
337 return (EINVAL);
338
339 err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, MII_BMCR,
340 BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART, 0);
341 if (err)
342 return (err);
343
344 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
345 BMCR_SPEED1000 | BMCR_SPEED100, set);
346 if (err)
347 return (err);
348
349 return (0);
350 }
351
352 static int
353 aq100x_get_link_status(struct cphy *phy, int *link_ok, int *speed, int *duplex,
354 int *fc)
355 {
356 int err;
357 unsigned int v, link = 0;
358
359 err = mdio_read(phy, MDIO_DEV_PMA_PMD, AQ_LINK_STAT, &v);
360 if (err)
361 return (err);
362 if (v == 0xffff || !(v & 1))
363 goto done;
364
365 err = mdio_read(phy, MDIO_DEV_ANEG, MII_BMCR, &v);
366 if (err)
367 return (err);
368 if (v & 0x8000)
369 goto done;
370 if (v & BMCR_ANENABLE) {
371
372 err = mdio_read(phy, MDIO_DEV_ANEG, 1, &v);
373 if (err)
374 return (err);
375 if ((v & 0x20) == 0)
376 goto done;
377
378 err = mdio_read(phy, MDIO_DEV_ANEG, AQ_ANEG_STAT, &v);
379 if (err)
380 return (err);
381
382 if (speed) {
383 switch (v & 0x6) {
384 case 0x6: *speed = SPEED_10000;
385 break;
386 case 0x4: *speed = SPEED_1000;
387 break;
388 case 0x2: *speed = SPEED_100;
389 break;
390 case 0x0: *speed = SPEED_10;
391 break;
392 }
393 }
394
395 if (duplex)
396 *duplex = v & 1 ? DUPLEX_FULL : DUPLEX_HALF;
397
398 if (fc) {
399 unsigned int lpa, adv;
400 err = mdio_read(phy, MDIO_DEV_ANEG, 0x13, &lpa);
401 if (!err)
402 err = mdio_read(phy, MDIO_DEV_ANEG,
403 AQ_100M_CTRL, &adv);
404 if (err)
405 return err;
406
407 if (lpa & adv & ADVERTISE_PAUSE_CAP)
408 *fc = PAUSE_RX | PAUSE_TX;
409 else if (lpa & ADVERTISE_PAUSE_CAP &&
410 lpa & ADVERTISE_PAUSE_ASYM &&
411 adv & ADVERTISE_PAUSE_ASYM)
412 *fc = PAUSE_TX;
413 else if (lpa & ADVERTISE_PAUSE_ASYM &&
414 adv & ADVERTISE_PAUSE_CAP)
415 *fc = PAUSE_RX;
416 else
417 *fc = 0;
418 }
419
420 } else {
421 err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v);
422 if (err)
423 return (err);
424
425 v &= BMCR_SPEED1000 | BMCR_SPEED100;
426 if (speed) {
427 if (v == (BMCR_SPEED1000 | BMCR_SPEED100))
428 *speed = SPEED_10000;
429 else if (v == BMCR_SPEED1000)
430 *speed = SPEED_1000;
431 else if (v == BMCR_SPEED100)
432 *speed = SPEED_100;
433 else
434 *speed = SPEED_10;
435 }
436
437 if (duplex)
438 *duplex = DUPLEX_FULL;
439 }
440
441 link = 1;
442 done:
443 if (link_ok)
444 *link_ok = link;
445 return (0);
446 }
447
448 static struct cphy_ops aq100x_ops = {
449 .reset = aq100x_reset,
450 .intr_enable = aq100x_intr_enable,
451 .intr_disable = aq100x_intr_disable,
452 .intr_clear = aq100x_intr_clear,
453 .intr_handler = aq100x_intr_handler,
454 .autoneg_enable = aq100x_autoneg_enable,
455 .autoneg_restart = aq100x_autoneg_restart,
456 .advertise = aq100x_advertise,
457 .set_loopback = aq100x_set_loopback,
458 .set_speed_duplex = aq100x_set_speed_duplex,
459 .get_link_status = aq100x_get_link_status,
460 .power_down = aq100x_power_down,
461 };
462
463 int
464 t3_aq100x_phy_prep(pinfo_t *pinfo, int phy_addr,
465 const struct mdio_ops *mdio_ops)
466 {
467 struct cphy *phy = &pinfo->phy;
468 unsigned int v, v2, gpio, wait;
469 int err;
470 adapter_t *adapter = pinfo->adapter;
471
472 cphy_init(&pinfo->phy, adapter, pinfo, phy_addr, &aq100x_ops, mdio_ops,
473 SUPPORTED_1000baseT_Full | SUPPORTED_10000baseT_Full |
474 SUPPORTED_TP | SUPPORTED_Autoneg | SUPPORTED_AUI |
475 SUPPORTED_MISC_IRQ, "1000/10GBASE-T");
476
477 /*
478 * Hard reset the PHY.
479 */
480 gpio = phy_addr ? F_GPIO10_OUT_VAL : F_GPIO6_OUT_VAL;
481 t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, 0);
482 msleep(1);
483 t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, gpio);
484
485 /*
486 * Give it enough time to load the firmware and get ready for mdio.
487 */
488 msleep(1000);
489 wait = 500; /* in 10ms increments */
490 do {
491 err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v);
492 if (err || v == 0xffff) {
493
494 /* Allow prep_adapter to succeed when ffff is read */
495
496 CH_WARN(adapter, "PHY%d: reset failed (0x%x, 0x%x).\n",
497 phy_addr, err, v);
498 goto done;
499 }
500
501 v &= BMCR_RESET;
502 if (v)
503 msleep(10);
504 } while (v && --wait);
505 if (v) {
506 CH_WARN(adapter, "PHY%d: reset timed out (0x%x).\n",
507 phy_addr, v);
508
509 goto done; /* let prep_adapter succeed */
510 }
511
512 /* Firmware version check. */
513 (void) mdio_read(phy, MDIO_DEV_VEND1, AQ_FW_VERSION, &v);
514 if (v < 0x115)
515 CH_WARN(adapter, "PHY%d: unknown firmware %d.%d\n", phy_addr,
516 v >> 8, v & 0xff);
517
518 /* The PHY should start in really-low-power mode. */
519 (void) mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v);
520 if ((v & BMCR_PDOWN) == 0)
521 CH_WARN(adapter, "PHY%d does not start in low power mode.\n",
522 phy_addr);
523
524 /*
525 * Verify XAUI and 1000-X settings, but let prep succeed no matter what.
526 */
527 v = v2 = 0;
528 (void) mdio_read(phy, MDIO_DEV_XGXS, AQ_XAUI_RX_CFG, &v);
529 (void) mdio_read(phy, MDIO_DEV_XGXS, AQ_XAUI_TX_CFG, &v2);
530 if (v != 0x1b || v2 != 0x1b)
531 CH_WARN(adapter, "PHY%d: incorrect XAUI settings "
532 "(0x%x, 0x%x).\n", phy_addr, v, v2);
533 v = 0;
534 (void) mdio_read(phy, MDIO_DEV_XGXS, AQ_XAUI_KX_CFG, &v);
535 if ((v & 0xf) != 0xf)
536 CH_WARN(adapter, "PHY%d: incorrect 1000-X settings "
537 "(0x%x).\n", phy_addr, v);
538
539 (void) aq100x_set_defaults(phy);
540 done:
541 return (err);
542 }
Cache object: a739680e2583b72b8c8089e78a05c150
|