Print this page
Just the 5719/5720 changes
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/io/bge/bge_mii.c
+++ new/usr/src/uts/common/io/bge/bge_mii.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
|
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 +/*
27 + * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
28 + */
29 +
26 30 #include "bge_impl.h"
27 31
28 32 /*
29 33 * Bit test macros, returning boolean_t values
30 34 */
31 35 #define BIS(w, b) (((w) & (b)) ? B_TRUE : B_FALSE)
32 36 #define BIC(w, b) (((w) & (b)) ? B_FALSE : B_TRUE)
33 37 #define UPORDOWN(x) ((x) ? "up" : "down")
34 38
35 39 /*
36 40 * ========== Copper (PHY) support ==========
37 41 */
38 42
39 43 #define BGE_DBG BGE_DBG_PHY /* debug flag for this code */
40 44
41 45 /*
42 46 * #defines:
43 47 * BGE_COPPER_WIRESPEED controls whether the Broadcom WireSpeed(tm)
44 48 * feature is enabled. We need to recheck whether this can be
45 49 * enabled; at one time it seemed to interact unpleasantly with the
46 50 * loopback modes.
47 51 *
48 52 * BGE_COPPER_IDLEOFF controls whether the (copper) PHY power is
49 53 * turned off when the PHY is idled i.e. during driver suspend().
50 54 * For now this is disabled because the chip doesn't seem to
51 55 * resume cleanly if the PHY power is turned off.
52 56 */
53 57 #define BGE_COPPER_WIRESPEED B_TRUE
54 58 #define BGE_COPPER_IDLEOFF B_FALSE
55 59
56 60 /*
57 61 * The arrays below can be indexed by the MODE bits from the Auxiliary
58 62 * Status register to determine the current speed/duplex settings.
59 63 */
60 64 static const int16_t bge_copper_link_speed[] = {
61 65 0, /* MII_AUX_STATUS_MODE_NONE */
62 66 10, /* MII_AUX_STATUS_MODE_10_H */
63 67 10, /* MII_AUX_STATUS_MODE_10_F */
64 68 100, /* MII_AUX_STATUS_MODE_100_H */
65 69 0, /* MII_AUX_STATUS_MODE_100_4 */
66 70 100, /* MII_AUX_STATUS_MODE_100_F */
67 71 1000, /* MII_AUX_STATUS_MODE_1000_H */
68 72 1000 /* MII_AUX_STATUS_MODE_1000_F */
69 73 };
70 74
71 75 static const int8_t bge_copper_link_duplex[] = {
72 76 LINK_DUPLEX_UNKNOWN, /* MII_AUX_STATUS_MODE_NONE */
73 77 LINK_DUPLEX_HALF, /* MII_AUX_STATUS_MODE_10_H */
74 78 LINK_DUPLEX_FULL, /* MII_AUX_STATUS_MODE_10_F */
75 79 LINK_DUPLEX_HALF, /* MII_AUX_STATUS_MODE_100_H */
76 80 LINK_DUPLEX_UNKNOWN, /* MII_AUX_STATUS_MODE_100_4 */
77 81 LINK_DUPLEX_FULL, /* MII_AUX_STATUS_MODE_100_F */
78 82 LINK_DUPLEX_HALF, /* MII_AUX_STATUS_MODE_1000_H */
79 83 LINK_DUPLEX_FULL /* MII_AUX_STATUS_MODE_1000_F */
80 84 };
81 85
82 86 static const int16_t bge_copper_link_speed_5906[] = {
83 87 0, /* MII_AUX_STATUS_MODE_NONE */
84 88 10, /* MII_AUX_STATUS_MODE_10_H */
85 89 10, /* MII_AUX_STATUS_MODE_10_F */
86 90 100, /* MII_AUX_STATUS_MODE_100_H */
87 91 0, /* MII_AUX_STATUS_MODE_100_4 */
88 92 100, /* MII_AUX_STATUS_MODE_100_F */
89 93 0, /* MII_AUX_STATUS_MODE_1000_H */
90 94 0 /* MII_AUX_STATUS_MODE_1000_F */
91 95 };
92 96
93 97 static const int8_t bge_copper_link_duplex_5906[] = {
94 98 LINK_DUPLEX_UNKNOWN, /* MII_AUX_STATUS_MODE_NONE */
95 99 LINK_DUPLEX_HALF, /* MII_AUX_STATUS_MODE_10_H */
96 100 LINK_DUPLEX_FULL, /* MII_AUX_STATUS_MODE_10_F */
97 101 LINK_DUPLEX_HALF, /* MII_AUX_STATUS_MODE_100_H */
98 102 LINK_DUPLEX_UNKNOWN, /* MII_AUX_STATUS_MODE_100_4 */
99 103 LINK_DUPLEX_FULL, /* MII_AUX_STATUS_MODE_100_F */
100 104 LINK_DUPLEX_UNKNOWN, /* MII_AUX_STATUS_MODE_1000_H */
101 105 LINK_DUPLEX_UNKNOWN /* MII_AUX_STATUS_MODE_1000_F */
102 106 };
103 107
104 108 #if BGE_DEBUGGING
105 109
106 110 static void
107 111 bge_phydump(bge_t *bgep, uint16_t mii_status, uint16_t aux)
108 112 {
109 113 uint16_t regs[32];
110 114 int i;
111 115
112 116 ASSERT(mutex_owned(bgep->genlock));
113 117
114 118 for (i = 0; i < 32; ++i)
115 119 switch (i) {
116 120 default:
117 121 regs[i] = bge_mii_get16(bgep, i);
118 122 break;
119 123
120 124 case MII_STATUS:
121 125 regs[i] = mii_status;
122 126 break;
123 127
124 128 case MII_AUX_STATUS:
125 129 regs[i] = aux;
126 130 break;
127 131
128 132 case 0x0b: case 0x0c: case 0x0d: case 0x0e:
129 133 case 0x15: case 0x16: case 0x17:
130 134 case 0x1c:
131 135 case 0x1f:
132 136 /* reserved registers -- don't read these */
133 137 regs[i] = 0;
134 138 break;
135 139 }
136 140
137 141 for (i = 0; i < 32; i += 8)
138 142 BGE_DEBUG(("bge_phydump: "
139 143 "0x%04x %04x %04x %04x %04x %04x %04x %04x",
140 144 regs[i+0], regs[i+1], regs[i+2], regs[i+3],
141 145 regs[i+4], regs[i+5], regs[i+6], regs[i+7]));
142 146 }
143 147
144 148 #endif /* BGE_DEBUGGING */
145 149
146 150 /*
147 151 * Basic low-level function to probe for a PHY
148 152 *
149 153 * Returns TRUE if the PHY responds with valid data, FALSE otherwise
150 154 */
151 155 static boolean_t
152 156 bge_phy_probe(bge_t *bgep)
153 157 {
154 158 uint16_t miicfg;
155 159 uint32_t nicsig, niccfg;
156 160
157 161 BGE_TRACE(("bge_phy_probe($%p)", (void *)bgep));
158 162
159 163 ASSERT(mutex_owned(bgep->genlock));
160 164
161 165 nicsig = bge_nic_read32(bgep, BGE_NIC_DATA_SIG_ADDR);
162 166 if (nicsig == BGE_NIC_DATA_SIG) {
163 167 niccfg = bge_nic_read32(bgep, BGE_NIC_DATA_NIC_CFG_ADDR);
164 168 switch (niccfg & BGE_NIC_CFG_PHY_TYPE_MASK) {
165 169 default:
166 170 case BGE_NIC_CFG_PHY_TYPE_COPPER:
167 171 return (B_TRUE);
168 172 case BGE_NIC_CFG_PHY_TYPE_FIBER:
169 173 return (B_FALSE);
170 174 }
171 175 } else {
172 176 /*
173 177 * Read the MII_STATUS register twice, in
174 178 * order to clear any sticky bits (but they should
175 179 * have been cleared by the RESET, I think).
176 180 */
177 181 miicfg = bge_mii_get16(bgep, MII_STATUS);
178 182 miicfg = bge_mii_get16(bgep, MII_STATUS);
179 183 BGE_DEBUG(("bge_phy_probe: status 0x%x", miicfg));
180 184
181 185 /*
182 186 * Now check the value read; it should have at least one bit set
183 187 * (for the device capabilities) and at least one clear (one of
184 188 * the error bits). So if we see all 0s or all 1s, there's a
185 189 * problem. In particular, bge_mii_get16() returns all 1s if
186 190 * communications fails ...
187 191 */
188 192 switch (miicfg) {
189 193 case 0x0000:
190 194 case 0xffff:
191 195 return (B_FALSE);
192 196
193 197 default :
194 198 return (B_TRUE);
195 199 }
196 200 }
197 201 }
198 202
199 203 /*
|
↓ open down ↓ |
164 lines elided |
↑ open up ↑ |
200 204 * Basic low-level function to reset the PHY.
201 205 * Doesn't incorporate any special-case workarounds.
202 206 *
203 207 * Returns TRUE on success, FALSE if the RESET bit doesn't clear
204 208 */
205 209 static boolean_t
206 210 bge_phy_reset(bge_t *bgep)
207 211 {
208 212 uint16_t control;
209 213 uint_t count;
214 + boolean_t ret = B_FALSE;
210 215
211 216 BGE_TRACE(("bge_phy_reset($%p)", (void *)bgep));
212 217
213 218 ASSERT(mutex_owned(bgep->genlock));
214 219
215 220 if (DEVICE_5906_SERIES_CHIPSETS(bgep)) {
216 221 drv_usecwait(40);
217 222 /* put PHY into ready state */
218 223 bge_reg_clr32(bgep, MISC_CONFIG_REG, MISC_CONFIG_EPHY_IDDQ);
219 224 (void) bge_reg_get32(bgep, MISC_CONFIG_REG); /* flush */
220 225 drv_usecwait(40);
221 226 }
222 227
223 228 /*
224 - * Set the PHY RESET bit, then wait up to 5 ms for it to self-clear
229 + * Set the PHY RESET bit, then wait up to 50 ms for it to self-clear
225 230 */
226 231 bge_mii_put16(bgep, MII_CONTROL, MII_CONTROL_RESET);
227 - for (count = 0; ++count < 1000; ) {
228 - drv_usecwait(5);
232 + for (count = 0; ++count < 5000; ) {
229 233 control = bge_mii_get16(bgep, MII_CONTROL);
230 - if (BIC(control, MII_CONTROL_RESET))
231 - return (B_TRUE);
234 + if (BIC(control, MII_CONTROL_RESET)) {
235 + drv_usecwait(40);
236 + ret = B_TRUE;
237 + break;
238 + }
239 + drv_usecwait(10);
232 240 }
233 241
234 - if (DEVICE_5906_SERIES_CHIPSETS(bgep))
242 + if (ret == B_TRUE && DEVICE_5906_SERIES_CHIPSETS(bgep))
235 243 (void) bge_adj_volt_5906(bgep);
236 244
237 - BGE_DEBUG(("bge_phy_reset: FAILED, control now 0x%x", control));
245 + if (ret == B_FALSE)
246 + BGE_DEBUG(("bge_phy_reset: FAILED, control now 0x%x", control));
238 247
239 - return (B_FALSE);
248 + return (ret);
240 249 }
241 250
242 251 /*
243 252 * Basic low-level function to powerdown the PHY, if supported
244 253 * If powerdown support is compiled out, this function does nothing.
245 254 */
246 255 static void
247 256 bge_phy_powerdown(bge_t *bgep)
248 257 {
249 258 BGE_TRACE(("bge_phy_powerdown"));
250 259 #if BGE_COPPER_IDLEOFF
251 260 bge_mii_put16(bgep, MII_CONTROL, MII_CONTROL_PWRDN);
252 261 #endif /* BGE_COPPER_IDLEOFF */
253 262 }
254 263
255 264 /*
256 265 * The following functions are based on sample code provided by
257 266 * Broadcom (20-June-2003), and implement workarounds said to be
258 267 * required on the early revisions of the BCM5703/4C.
259 268 *
260 269 * The registers and values used are mostly UNDOCUMENTED, and
261 270 * therefore don't have symbolic names ;-(
262 271 *
263 272 * Many of the comments are straight out of the Broadcom code:
264 273 * even where the code has been restructured, the original
265 274 * comments have been preserved in order to explain what these
266 275 * undocumented registers & values are all about ...
267 276 */
268 277
269 278 static void
270 279 bge_phy_macro_wait(bge_t *bgep)
271 280 {
272 281 uint_t count;
273 282
274 283 for (count = 100; --count; )
275 284 if ((bge_mii_get16(bgep, 0x16) & 0x1000) == 0)
276 285 break;
277 286 }
278 287
279 288 /*
280 289 * PHY test data pattern:
281 290 *
282 291 * For 5703/04, each DFE TAP has 21-bits (low word 15, hi word 6)
283 292 * For 5705, each DFE TAP has 19-bits (low word 15, hi word 4)
284 293 * For simplicity, we check only 19-bits, so we don't have to
285 294 * distinguish which chip it is.
286 295 * the LO word contains 15 bits, make sure pattern data is < 0x7fff
287 296 * the HI word contains 6 bits, make sure pattern data is < 0x003f
288 297 */
289 298 #define N_CHANNELS 4
290 299 #define N_TAPS 3
291 300
292 301 static struct {
293 302 uint16_t lo;
294 303 uint16_t hi;
295 304 } tap_data[N_CHANNELS][N_TAPS] = {
296 305 {
297 306 { 0x5555, 0x0005 }, /* ch0, TAP 0, LO/HI pattern */
298 307 { 0x2aaa, 0x000a }, /* ch0, TAP 1, LO/HI pattern */
299 308 { 0x3456, 0x0003 } /* ch0, TAP 2, LO/HI pattern */
300 309 },
301 310 {
302 311 { 0x2aaa, 0x000a }, /* ch1, TAP 0, LO/HI pattern */
303 312 { 0x3333, 0x0003 }, /* ch1, TAP 1, LO/HI pattern */
304 313 { 0x789a, 0x0005 } /* ch1, TAP 2, LO/HI pattern */
305 314 },
306 315 {
307 316 { 0x5a5a, 0x0005 }, /* ch2, TAP 0, LO/HI pattern */
308 317 { 0x2a6a, 0x000a }, /* ch2, TAP 1, LO/HI pattern */
309 318 { 0x1bcd, 0x0003 } /* ch2, TAP 2, LO/HI pattern */
310 319 },
311 320 {
312 321 { 0x2a5a, 0x000a }, /* ch3, TAP 0, LO/HI pattern */
313 322 { 0x33c3, 0x0003 }, /* ch3, TAP 1, LO/HI pattern */
314 323 { 0x2ef1, 0x0005 } /* ch3, TAP 2, LO/HI pattern */
315 324 }
316 325 };
317 326
318 327 /*
319 328 * Check whether the PHY has locked up after a RESET.
320 329 *
321 330 * Returns TRUE if it did, FALSE is it's OK ;-)
322 331 */
323 332 static boolean_t
324 333 bge_phy_locked_up(bge_t *bgep)
325 334 {
326 335 uint16_t dataLo;
327 336 uint16_t dataHi;
328 337 uint_t chan;
329 338 uint_t tap;
330 339
331 340 /*
332 341 * Check TAPs for all 4 channels, as soon as we see a lockup
333 342 * we'll stop checking.
334 343 */
335 344 for (chan = 0; chan < N_CHANNELS; ++chan) {
336 345 /* Select channel and set TAP index to 0 */
337 346 bge_mii_put16(bgep, 0x17, (chan << 13) | 0x0200);
338 347 /* Freeze filter again just to be safe */
339 348 bge_mii_put16(bgep, 0x16, 0x0002);
340 349
341 350 /*
342 351 * Write fixed pattern to the RAM, 3 TAPs for
343 352 * each channel, each TAP have 2 WORDs (LO/HI)
344 353 */
345 354 for (tap = 0; tap < N_TAPS; ++tap) {
346 355 bge_mii_put16(bgep, 0x15, tap_data[chan][tap].lo);
347 356 bge_mii_put16(bgep, 0x15, tap_data[chan][tap].hi);
348 357 }
349 358
350 359 /*
351 360 * Active PHY's Macro operation to write DFE
352 361 * TAP from RAM, and wait for Macro to complete.
353 362 */
354 363 bge_mii_put16(bgep, 0x16, 0x0202);
355 364 bge_phy_macro_wait(bgep);
356 365
357 366 /*
358 367 * Done with write phase, now begin read phase.
359 368 */
360 369
361 370 /* Select channel and set TAP index to 0 */
362 371 bge_mii_put16(bgep, 0x17, (chan << 13) | 0x0200);
363 372
364 373 /*
365 374 * Active PHY's Macro operation to load DFE
366 375 * TAP to RAM, and wait for Macro to complete
367 376 */
368 377 bge_mii_put16(bgep, 0x16, 0x0082);
369 378 bge_phy_macro_wait(bgep);
370 379
371 380 /* Enable "pre-fetch" */
372 381 bge_mii_put16(bgep, 0x16, 0x0802);
373 382 bge_phy_macro_wait(bgep);
374 383
375 384 /*
376 385 * Read back the TAP values. 3 TAPs for each
377 386 * channel, each TAP have 2 WORDs (LO/HI)
378 387 */
379 388 for (tap = 0; tap < N_TAPS; ++tap) {
380 389 /*
381 390 * Read Lo/Hi then wait for 'done' is faster.
382 391 * For DFE TAP, the HI word contains 6 bits,
383 392 * LO word contains 15 bits
384 393 */
385 394 dataLo = bge_mii_get16(bgep, 0x15) & 0x7fff;
386 395 dataHi = bge_mii_get16(bgep, 0x15) & 0x003f;
387 396 bge_phy_macro_wait(bgep);
388 397
389 398 /*
390 399 * Check if what we wrote is what we read back.
391 400 * If failed, then the PHY is locked up, we need
392 401 * to do PHY reset again
393 402 */
394 403 if (dataLo != tap_data[chan][tap].lo)
395 404 return (B_TRUE); /* wedged! */
396 405
397 406 if (dataHi != tap_data[chan][tap].hi)
398 407 return (B_TRUE); /* wedged! */
399 408 }
400 409 }
401 410
402 411 /*
403 412 * The PHY isn't locked up ;-)
404 413 */
405 414 return (B_FALSE);
406 415 }
407 416
408 417 /*
409 418 * Special-case code to reset the PHY on the 5702/5703/5704C/5705/5782.
410 419 * Tries up to 5 times to recover from failure to reset or PHY lockup.
411 420 *
412 421 * Returns TRUE on success, FALSE if there's an unrecoverable problem
413 422 */
414 423 static boolean_t
415 424 bge_phy_reset_and_check(bge_t *bgep)
416 425 {
417 426 boolean_t reset_success;
418 427 boolean_t phy_locked;
419 428 uint16_t extctrl;
420 429 uint16_t gigctrl;
421 430 uint_t retries;
422 431
423 432 for (retries = 0; retries < 5; ++retries) {
424 433 /* Issue a phy reset, and wait for reset to complete */
425 434 /* Assuming reset is successful first */
426 435 reset_success = bge_phy_reset(bgep);
427 436
428 437 /*
429 438 * Now go check the DFE TAPs to see if locked up, but
430 439 * first, we need to set up PHY so we can read DFE
431 440 * TAPs.
432 441 */
433 442
434 443 /*
435 444 * Disable Transmitter and Interrupt, while we play
436 445 * with the PHY registers, so the link partner won't
437 446 * see any strange data and the Driver won't see any
438 447 * interrupts.
439 448 */
440 449 extctrl = bge_mii_get16(bgep, 0x10);
441 450 bge_mii_put16(bgep, 0x10, extctrl | 0x3000);
442 451
443 452 /* Setup Full-Duplex, 1000 mbps */
444 453 bge_mii_put16(bgep, 0x0, 0x0140);
445 454
446 455 /* Set to Master mode */
447 456 gigctrl = bge_mii_get16(bgep, 0x9);
448 457 bge_mii_put16(bgep, 0x9, 0x1800);
449 458
450 459 /* Enable SM_DSP_CLOCK & 6dB */
451 460 bge_mii_put16(bgep, 0x18, 0x0c00); /* "the ADC fix" */
452 461
453 462 /* Work-arounds */
454 463 bge_mii_put16(bgep, 0x17, 0x201f);
455 464 bge_mii_put16(bgep, 0x15, 0x2aaa);
456 465
457 466 /* More workarounds */
458 467 bge_mii_put16(bgep, 0x17, 0x000a);
459 468 bge_mii_put16(bgep, 0x15, 0x0323); /* "the Gamma fix" */
460 469
461 470 /* Blocks the PHY control access */
462 471 bge_mii_put16(bgep, 0x17, 0x8005);
463 472 bge_mii_put16(bgep, 0x15, 0x0800);
464 473
465 474 /* Test whether PHY locked up ;-( */
466 475 phy_locked = bge_phy_locked_up(bgep);
467 476 if (reset_success && !phy_locked)
468 477 break;
469 478
470 479 /*
471 480 * Some problem here ... log it & retry
472 481 */
473 482 if (!reset_success)
474 483 BGE_REPORT((bgep, "PHY didn't reset!"));
475 484 if (phy_locked)
476 485 BGE_REPORT((bgep, "PHY locked up!"));
477 486 }
478 487
479 488 /* Remove block phy control */
480 489 bge_mii_put16(bgep, 0x17, 0x8005);
481 490 bge_mii_put16(bgep, 0x15, 0x0000);
482 491
483 492 /* Unfreeze DFE TAP filter for all channels */
484 493 bge_mii_put16(bgep, 0x17, 0x8200);
485 494 bge_mii_put16(bgep, 0x16, 0x0000);
486 495
487 496 /* Restore PHY back to operating state */
488 497 bge_mii_put16(bgep, 0x18, 0x0400);
489 498
490 499 /* Restore 1000BASE-T Control Register */
491 500 bge_mii_put16(bgep, 0x9, gigctrl);
492 501
493 502 /* Enable transmitter and interrupt */
494 503 extctrl = bge_mii_get16(bgep, 0x10);
495 504 bge_mii_put16(bgep, 0x10, extctrl & ~0x3000);
496 505
497 506 if (DEVICE_5906_SERIES_CHIPSETS(bgep))
498 507 (void) bge_adj_volt_5906(bgep);
499 508
500 509 if (!reset_success)
501 510 bge_fm_ereport(bgep, DDI_FM_DEVICE_NO_RESPONSE);
502 511 else if (phy_locked)
503 512 bge_fm_ereport(bgep, DDI_FM_DEVICE_INVAL_STATE);
504 513 return (reset_success && !phy_locked);
505 514 }
506 515
507 516 static void
508 517 bge_phy_tweak_gmii(bge_t *bgep)
509 518 {
510 519 /* Tweak GMII timing */
511 520 bge_mii_put16(bgep, 0x1c, 0x8d68);
512 521 bge_mii_put16(bgep, 0x1c, 0x8d68);
513 522 }
514 523
515 524 /* Bit Error Rate reduction fix */
516 525 static void
517 526 bge_phy_bit_err_fix(bge_t *bgep)
518 527 {
519 528 bge_mii_put16(bgep, 0x18, 0x0c00);
520 529 bge_mii_put16(bgep, 0x17, 0x000a);
521 530 bge_mii_put16(bgep, 0x15, 0x310b);
522 531 bge_mii_put16(bgep, 0x17, 0x201f);
523 532 bge_mii_put16(bgep, 0x15, 0x9506);
524 533 bge_mii_put16(bgep, 0x17, 0x401f);
525 534 bge_mii_put16(bgep, 0x15, 0x14e2);
526 535 bge_mii_put16(bgep, 0x18, 0x0400);
527 536 }
528 537
529 538 /*
530 539 * End of Broadcom-derived workaround code *
531 540 */
532 541
533 542 static int
|
↓ open down ↓ |
284 lines elided |
↑ open up ↑ |
534 543 bge_restart_copper(bge_t *bgep, boolean_t powerdown)
535 544 {
536 545 uint16_t phy_status;
537 546 boolean_t reset_ok;
538 547 uint16_t extctrl, auxctrl;
539 548
540 549 BGE_TRACE(("bge_restart_copper($%p, %d)", (void *)bgep, powerdown));
541 550
542 551 ASSERT(mutex_owned(bgep->genlock));
543 552
544 - switch (MHCR_CHIP_ASIC_REV(bgep->chipid.asic_rev)) {
545 - default:
546 - /*
547 - * Shouldn't happen; it means we don't recognise this chip.
548 - * It's probably a new one, so we'll try our best anyway ...
549 - */
550 - case MHCR_CHIP_ASIC_REV_5703:
551 - case MHCR_CHIP_ASIC_REV_5704:
552 - case MHCR_CHIP_ASIC_REV_5705:
553 - case MHCR_CHIP_ASIC_REV_5752:
554 - case MHCR_CHIP_ASIC_REV_5714:
555 - case MHCR_CHIP_ASIC_REV_5715:
556 - reset_ok = bge_phy_reset_and_check(bgep);
557 - break;
558 -
559 - case MHCR_CHIP_ASIC_REV_5906:
560 - case MHCR_CHIP_ASIC_REV_5700:
561 - case MHCR_CHIP_ASIC_REV_5701:
562 - case MHCR_CHIP_ASIC_REV_5723:
563 - case MHCR_CHIP_ASIC_REV_5721_5751:
564 - /*
565 - * Just a plain reset; the "check" code breaks these chips
566 - */
553 + if (bgep->chipid.flags & CHIP_FLAG_NO_CHECK_RESET) {
567 554 reset_ok = bge_phy_reset(bgep);
568 555 if (!reset_ok)
569 556 bge_fm_ereport(bgep, DDI_FM_DEVICE_NO_RESPONSE);
570 - break;
557 + } else {
558 + reset_ok = bge_phy_reset_and_check(bgep);
571 559 }
560 +
572 561 if (!reset_ok) {
573 562 BGE_REPORT((bgep, "PHY failed to reset correctly"));
574 563 return (DDI_FAILURE);
575 564 }
576 565
577 566 /*
578 567 * Step 5: disable WOL (not required after RESET)
579 568 *
580 569 * Step 6: refer to errata
581 570 */
582 571 switch (bgep->chipid.asic_rev) {
|
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
583 572 default:
584 573 break;
585 574
586 575 case MHCR_CHIP_REV_5704_A0:
587 576 bge_phy_tweak_gmii(bgep);
588 577 break;
589 578 }
590 579
591 580 switch (MHCR_CHIP_ASIC_REV(bgep->chipid.asic_rev)) {
592 581 case MHCR_CHIP_ASIC_REV_5705:
593 - case MHCR_CHIP_ASIC_REV_5721_5751:
582 + case MHCR_CHIP_ASIC_REV_5750:
594 583 bge_phy_bit_err_fix(bgep);
595 584 break;
596 585 }
597 586
598 587 if (!(bgep->chipid.flags & CHIP_FLAG_NO_JUMBO) &&
599 588 (bgep->chipid.default_mtu > BGE_DEFAULT_MTU)) {
600 589 /* Set the GMII Fifo Elasticity to high latency */
601 590 extctrl = bge_mii_get16(bgep, 0x10);
602 591 bge_mii_put16(bgep, 0x10, extctrl | 0x1);
603 592
604 593 /* Allow reception of extended length packets */
605 594 bge_mii_put16(bgep, MII_AUX_CONTROL, 0x0007);
606 595 auxctrl = bge_mii_get16(bgep, MII_AUX_CONTROL);
607 596 auxctrl |= 0x4000;
608 597 bge_mii_put16(bgep, MII_AUX_CONTROL, auxctrl);
609 598 }
610 599
611 600 /*
612 601 * Step 7: read the MII_INTR_STATUS register twice,
613 602 * in order to clear any sticky bits (but they should
614 603 * have been cleared by the RESET, I think), and we're
615 604 * not using PHY interrupts anyway.
616 605 *
617 606 * Step 8: enable the PHY to interrupt on link status
618 607 * change (not required)
619 608 *
620 609 * Step 9: configure PHY LED Mode - not applicable?
621 610 *
622 611 * Step 10: read the MII_STATUS register twice, in
623 612 * order to clear any sticky bits (but they should
624 613 * have been cleared by the RESET, I think).
625 614 */
626 615 phy_status = bge_mii_get16(bgep, MII_STATUS);
627 616 phy_status = bge_mii_get16(bgep, MII_STATUS);
628 617 BGE_DEBUG(("bge_restart_copper: status 0x%x", phy_status));
629 618
630 619 /*
631 620 * Finally, shut down the PHY, if required
632 621 */
633 622 if (powerdown)
634 623 bge_phy_powerdown(bgep);
635 624 return (DDI_SUCCESS);
636 625 }
637 626
638 627 /*
639 628 * Synchronise the (copper) PHY's speed/duplex/autonegotiation capabilities
640 629 * and advertisements with the required settings as specified by the various
641 630 * param_* variables that can be poked via the NDD interface.
642 631 *
643 632 * We always reset the PHY and reprogram *all* the relevant registers,
644 633 * not just those changed. This should cause the link to go down, and then
645 634 * back up again once the link is stable and autonegotiation (if enabled)
646 635 * is complete. We should get a link state change interrupt somewhere along
647 636 * the way ...
648 637 *
649 638 * NOTE: <genlock> must already be held by the caller
650 639 */
651 640 static int
652 641 bge_update_copper(bge_t *bgep)
653 642 {
654 643 boolean_t adv_autoneg;
655 644 boolean_t adv_pause;
656 645 boolean_t adv_asym_pause;
657 646 boolean_t adv_1000fdx;
658 647 boolean_t adv_1000hdx;
659 648 boolean_t adv_100fdx;
660 649 boolean_t adv_100hdx;
661 650 boolean_t adv_10fdx;
662 651 boolean_t adv_10hdx;
663 652
664 653 uint16_t control;
665 654 uint16_t gigctrl;
666 655 uint16_t auxctrl;
667 656 uint16_t anar;
668 657
669 658 BGE_TRACE(("bge_update_copper($%p)", (void *)bgep));
670 659
671 660 ASSERT(mutex_owned(bgep->genlock));
672 661
673 662 BGE_DEBUG(("bge_update_copper: autoneg %d "
674 663 "pause %d asym_pause %d "
675 664 "1000fdx %d 1000hdx %d "
676 665 "100fdx %d 100hdx %d "
677 666 "10fdx %d 10hdx %d ",
678 667 bgep->param_adv_autoneg,
679 668 bgep->param_adv_pause, bgep->param_adv_asym_pause,
680 669 bgep->param_adv_1000fdx, bgep->param_adv_1000hdx,
681 670 bgep->param_adv_100fdx, bgep->param_adv_100hdx,
682 671 bgep->param_adv_10fdx, bgep->param_adv_10hdx));
683 672
684 673 control = gigctrl = auxctrl = anar = 0;
685 674
686 675 /*
687 676 * PHY settings are normally based on the param_* variables,
688 677 * but if any loopback mode is in effect, that takes precedence.
689 678 *
690 679 * BGE supports MAC-internal loopback, PHY-internal loopback,
691 680 * and External loopback at a variety of speeds (with a special
692 681 * cable). In all cases, autoneg is turned OFF, full-duplex
693 682 * is turned ON, and the speed/mastership is forced.
694 683 */
695 684 switch (bgep->param_loop_mode) {
696 685 case BGE_LOOP_NONE:
697 686 default:
698 687 adv_autoneg = bgep->param_adv_autoneg;
699 688 adv_pause = bgep->param_adv_pause;
700 689 adv_asym_pause = bgep->param_adv_asym_pause;
701 690 adv_1000fdx = bgep->param_adv_1000fdx;
702 691 adv_1000hdx = bgep->param_adv_1000hdx;
703 692 adv_100fdx = bgep->param_adv_100fdx;
704 693 adv_100hdx = bgep->param_adv_100hdx;
705 694 adv_10fdx = bgep->param_adv_10fdx;
706 695 adv_10hdx = bgep->param_adv_10hdx;
707 696 break;
708 697
709 698 case BGE_LOOP_EXTERNAL_1000:
710 699 case BGE_LOOP_EXTERNAL_100:
711 700 case BGE_LOOP_EXTERNAL_10:
712 701 case BGE_LOOP_INTERNAL_PHY:
713 702 case BGE_LOOP_INTERNAL_MAC:
714 703 adv_autoneg = adv_pause = adv_asym_pause = B_FALSE;
715 704 adv_1000fdx = adv_100fdx = adv_10fdx = B_FALSE;
716 705 adv_1000hdx = adv_100hdx = adv_10hdx = B_FALSE;
717 706 bgep->param_link_duplex = LINK_DUPLEX_FULL;
718 707
719 708 switch (bgep->param_loop_mode) {
720 709 case BGE_LOOP_EXTERNAL_1000:
721 710 bgep->param_link_speed = 1000;
722 711 adv_1000fdx = B_TRUE;
723 712 auxctrl = MII_AUX_CTRL_NORM_EXT_LOOPBACK;
724 713 gigctrl |= MII_MSCONTROL_MANUAL;
725 714 gigctrl |= MII_MSCONTROL_MASTER;
726 715 break;
727 716
728 717 case BGE_LOOP_EXTERNAL_100:
729 718 bgep->param_link_speed = 100;
730 719 adv_100fdx = B_TRUE;
731 720 auxctrl = MII_AUX_CTRL_NORM_EXT_LOOPBACK;
732 721 break;
733 722
734 723 case BGE_LOOP_EXTERNAL_10:
735 724 bgep->param_link_speed = 10;
736 725 adv_10fdx = B_TRUE;
737 726 auxctrl = MII_AUX_CTRL_NORM_EXT_LOOPBACK;
738 727 break;
739 728
740 729 case BGE_LOOP_INTERNAL_PHY:
741 730 bgep->param_link_speed = 1000;
742 731 adv_1000fdx = B_TRUE;
743 732 control = MII_CONTROL_LOOPBACK;
744 733 break;
745 734
746 735 case BGE_LOOP_INTERNAL_MAC:
747 736 bgep->param_link_speed = 1000;
748 737 adv_1000fdx = B_TRUE;
749 738 break;
750 739 }
751 740 }
752 741
753 742 BGE_DEBUG(("bge_update_copper: autoneg %d "
754 743 "pause %d asym_pause %d "
755 744 "1000fdx %d 1000hdx %d "
756 745 "100fdx %d 100hdx %d "
757 746 "10fdx %d 10hdx %d ",
758 747 adv_autoneg,
759 748 adv_pause, adv_asym_pause,
760 749 adv_1000fdx, adv_1000hdx,
761 750 adv_100fdx, adv_100hdx,
762 751 adv_10fdx, adv_10hdx));
763 752
764 753 /*
765 754 * We should have at least one technology capability set;
766 755 * if not, we select a default of 1000Mb/s full-duplex
767 756 */
768 757 if (!adv_1000fdx && !adv_100fdx && !adv_10fdx &&
769 758 !adv_1000hdx && !adv_100hdx && !adv_10hdx)
770 759 adv_1000fdx = B_TRUE;
771 760
772 761 /*
773 762 * Now transform the adv_* variables into the proper settings
774 763 * of the PHY registers ...
775 764 *
776 765 * If autonegotiation is (now) enabled, we want to trigger
777 766 * a new autonegotiation cycle once the PHY has been
778 767 * programmed with the capabilities to be advertised.
779 768 */
780 769 if (adv_autoneg)
781 770 control |= MII_CONTROL_ANE|MII_CONTROL_RSAN;
782 771
783 772 if (adv_1000fdx)
784 773 control |= MII_CONTROL_1GB|MII_CONTROL_FDUPLEX;
785 774 else if (adv_1000hdx)
786 775 control |= MII_CONTROL_1GB;
787 776 else if (adv_100fdx)
788 777 control |= MII_CONTROL_100MB|MII_CONTROL_FDUPLEX;
789 778 else if (adv_100hdx)
790 779 control |= MII_CONTROL_100MB;
791 780 else if (adv_10fdx)
792 781 control |= MII_CONTROL_FDUPLEX;
793 782 else if (adv_10hdx)
794 783 control |= 0;
795 784 else
796 785 { _NOTE(EMPTY); } /* Can't get here anyway ... */
797 786
798 787 if (adv_1000fdx)
799 788 gigctrl |= MII_MSCONTROL_1000T_FD;
800 789 if (adv_1000hdx)
801 790 gigctrl |= MII_MSCONTROL_1000T;
802 791
803 792 if (adv_100fdx)
804 793 anar |= MII_ABILITY_100BASE_TX_FD;
805 794 if (adv_100hdx)
806 795 anar |= MII_ABILITY_100BASE_TX;
807 796 if (adv_10fdx)
808 797 anar |= MII_ABILITY_10BASE_T_FD;
809 798 if (adv_10hdx)
810 799 anar |= MII_ABILITY_10BASE_T;
811 800
812 801 if (adv_pause)
813 802 anar |= MII_ABILITY_PAUSE;
814 803 if (adv_asym_pause)
815 804 anar |= MII_ABILITY_ASMPAUSE;
816 805
817 806 /*
818 807 * Munge in any other fixed bits we require ...
819 808 */
820 809 anar |= MII_AN_SELECTOR_8023;
821 810 auxctrl |= MII_AUX_CTRL_NORM_TX_MODE;
822 811 auxctrl |= MII_AUX_CTRL_NORMAL;
823 812
824 813 /*
825 814 * Restart the PHY and write the new values. Note the
826 815 * time, so that we can say whether subsequent link state
827 816 * changes can be attributed to our reprogramming the PHY
828 817 */
829 818 if ((*bgep->physops->phys_restart)(bgep, B_FALSE) == DDI_FAILURE)
830 819 return (DDI_FAILURE);
831 820 bge_mii_put16(bgep, MII_AN_ADVERT, anar);
832 821 if (auxctrl & MII_AUX_CTRL_NORM_EXT_LOOPBACK)
833 822 bge_mii_put16(bgep, MII_AUX_CONTROL, auxctrl);
834 823 bge_mii_put16(bgep, MII_MSCONTROL, gigctrl);
835 824 bge_mii_put16(bgep, MII_CONTROL, control);
836 825
837 826 BGE_DEBUG(("bge_update_copper: anar <- 0x%x", anar));
838 827 BGE_DEBUG(("bge_update_copper: auxctrl <- 0x%x", auxctrl));
839 828 BGE_DEBUG(("bge_update_copper: gigctrl <- 0x%x", gigctrl));
840 829 BGE_DEBUG(("bge_update_copper: control <- 0x%x", control));
841 830
842 831 #if BGE_COPPER_WIRESPEED
843 832 /*
844 833 * Enable the 'wire-speed' feature, if the chip supports it
845 834 * and we haven't got (any) loopback mode selected.
846 835 */
847 836 switch (bgep->chipid.device) {
848 837 case DEVICE_ID_5700:
849 838 case DEVICE_ID_5700x:
850 839 case DEVICE_ID_5705C:
851 840 case DEVICE_ID_5782:
852 841 /*
853 842 * These chips are known or assumed not to support it
854 843 */
855 844 break;
856 845
857 846 default:
858 847 /*
859 848 * All other Broadcom chips are expected to support it.
860 849 */
861 850 if (bgep->param_loop_mode == BGE_LOOP_NONE)
862 851 bge_mii_put16(bgep, MII_AUX_CONTROL,
863 852 MII_AUX_CTRL_MISC_WRITE_ENABLE |
864 853 MII_AUX_CTRL_MISC_WIRE_SPEED |
865 854 MII_AUX_CTRL_MISC);
866 855 break;
867 856 }
868 857 #endif /* BGE_COPPER_WIRESPEED */
869 858 return (DDI_SUCCESS);
870 859 }
871 860
872 861 static boolean_t
873 862 bge_check_copper(bge_t *bgep, boolean_t recheck)
874 863 {
875 864 uint32_t emac_status;
876 865 uint16_t mii_status;
877 866 uint16_t aux;
878 867 uint_t mode;
879 868 boolean_t linkup;
880 869
881 870 /*
882 871 * Step 10: read the status from the PHY (which is self-clearing
883 872 * on read!); also read & clear the main (Ethernet) MAC status
884 873 * (the relevant bits of this are write-one-to-clear).
885 874 */
886 875 mii_status = bge_mii_get16(bgep, MII_STATUS);
887 876 emac_status = bge_reg_get32(bgep, ETHERNET_MAC_STATUS_REG);
888 877 bge_reg_put32(bgep, ETHERNET_MAC_STATUS_REG, emac_status);
889 878
890 879 BGE_DEBUG(("bge_check_copper: link %d/%s, MII status 0x%x "
891 880 "(was 0x%x), Ethernet MAC status 0x%x",
892 881 bgep->link_state, UPORDOWN(bgep->param_link_up), mii_status,
893 882 bgep->phy_gen_status, emac_status));
894 883
895 884 /*
896 885 * If the PHY status hasn't changed since last we looked, and
897 886 * we not forcing a recheck (i.e. the link state was already
898 887 * known), there's nothing to do.
899 888 */
900 889 if (mii_status == bgep->phy_gen_status && !recheck)
901 890 return (B_FALSE);
902 891
903 892 do {
904 893 /*
905 894 * Step 11: read AUX STATUS register to find speed/duplex
906 895 */
907 896 aux = bge_mii_get16(bgep, MII_AUX_STATUS);
908 897 BGE_CDB(bge_phydump, (bgep, mii_status, aux));
909 898
910 899 /*
911 900 * We will only consider the link UP if all the readings
912 901 * are consistent and give meaningful results ...
913 902 */
914 903 mode = aux & MII_AUX_STATUS_MODE_MASK;
915 904 mode >>= MII_AUX_STATUS_MODE_SHIFT;
916 905 if (DEVICE_5906_SERIES_CHIPSETS(bgep)) {
917 906 linkup = BIS(aux, MII_AUX_STATUS_LINKUP);
918 907 linkup &= BIS(mii_status, MII_STATUS_LINKUP);
919 908 } else {
920 909 linkup = bge_copper_link_speed[mode] > 0;
921 910 linkup &= bge_copper_link_duplex[mode] !=
922 911 LINK_DUPLEX_UNKNOWN;
923 912 linkup &= BIS(aux, MII_AUX_STATUS_LINKUP);
924 913 linkup &= BIS(mii_status, MII_STATUS_LINKUP);
925 914 }
926 915
927 916 BGE_DEBUG(("bge_check_copper: MII status 0x%x aux 0x%x "
928 917 "=> mode %d (%s)",
929 918 mii_status, aux,
930 919 mode, UPORDOWN(linkup)));
931 920
932 921 /*
933 922 * Record current register values, then reread status
934 923 * register & loop until it stabilises ...
935 924 */
936 925 bgep->phy_aux_status = aux;
937 926 bgep->phy_gen_status = mii_status;
938 927 mii_status = bge_mii_get16(bgep, MII_STATUS);
939 928 } while (mii_status != bgep->phy_gen_status);
940 929
941 930 /*
942 931 * Assume very little ...
943 932 */
944 933 bgep->param_lp_autoneg = B_FALSE;
945 934 bgep->param_lp_1000fdx = B_FALSE;
946 935 bgep->param_lp_1000hdx = B_FALSE;
947 936 bgep->param_lp_100fdx = B_FALSE;
948 937 bgep->param_lp_100hdx = B_FALSE;
949 938 bgep->param_lp_10fdx = B_FALSE;
950 939 bgep->param_lp_10hdx = B_FALSE;
951 940 bgep->param_lp_pause = B_FALSE;
952 941 bgep->param_lp_asym_pause = B_FALSE;
953 942 bgep->param_link_autoneg = B_FALSE;
954 943 bgep->param_link_tx_pause = B_FALSE;
955 944 if (bgep->param_adv_autoneg)
956 945 bgep->param_link_rx_pause = B_FALSE;
957 946 else
958 947 bgep->param_link_rx_pause = bgep->param_adv_pause;
959 948
960 949 /*
961 950 * Discover all the link partner's abilities.
962 951 * These are scattered through various registers ...
963 952 */
964 953 if (BIS(aux, MII_AUX_STATUS_LP_ANEG_ABLE)) {
965 954 bgep->param_lp_autoneg = B_TRUE;
966 955 bgep->param_link_autoneg = B_TRUE;
967 956 bgep->param_link_tx_pause = BIS(aux, MII_AUX_STATUS_TX_PAUSE);
968 957 bgep->param_link_rx_pause = BIS(aux, MII_AUX_STATUS_RX_PAUSE);
969 958
970 959 aux = bge_mii_get16(bgep, MII_MSSTATUS);
971 960 bgep->param_lp_1000fdx = BIS(aux, MII_MSSTATUS_LP1000T_FD);
972 961 bgep->param_lp_1000hdx = BIS(aux, MII_MSSTATUS_LP1000T);
973 962
974 963 aux = bge_mii_get16(bgep, MII_AN_LPABLE);
975 964 bgep->param_lp_100fdx = BIS(aux, MII_ABILITY_100BASE_TX_FD);
976 965 bgep->param_lp_100hdx = BIS(aux, MII_ABILITY_100BASE_TX);
977 966 bgep->param_lp_10fdx = BIS(aux, MII_ABILITY_10BASE_T_FD);
978 967 bgep->param_lp_10hdx = BIS(aux, MII_ABILITY_10BASE_T);
979 968 bgep->param_lp_pause = BIS(aux, MII_ABILITY_PAUSE);
980 969 bgep->param_lp_asym_pause = BIS(aux, MII_ABILITY_ASMPAUSE);
981 970 }
982 971
983 972 /*
984 973 * Step 12: update ndd-visible state parameters, BUT!
985 974 * we don't transfer the new state to <link_state> just yet;
986 975 * instead we mark the <link_state> as UNKNOWN, and our caller
987 976 * will resolve it once the status has stopped changing and
988 977 * been stable for several seconds.
989 978 */
990 979 BGE_DEBUG(("bge_check_copper: link was %s speed %d duplex %d",
991 980 UPORDOWN(bgep->param_link_up),
992 981 bgep->param_link_speed,
993 982 bgep->param_link_duplex));
994 983
995 984 if (!linkup)
996 985 mode = MII_AUX_STATUS_MODE_NONE;
997 986 bgep->param_link_up = linkup;
998 987 bgep->link_state = LINK_STATE_UNKNOWN;
999 988 if (DEVICE_5906_SERIES_CHIPSETS(bgep)) {
1000 989 if (bgep->phy_aux_status & MII_AUX_STATUS_NEG_ENABLED_5906) {
1001 990 bgep->param_link_speed =
1002 991 bge_copper_link_speed_5906[mode];
1003 992 bgep->param_link_duplex =
1004 993 bge_copper_link_duplex_5906[mode];
1005 994 } else {
1006 995 bgep->param_link_speed = (bgep->phy_aux_status &
1007 996 MII_AUX_STATUS_SPEED_IND_5906) ? 100 : 10;
1008 997 bgep->param_link_duplex = (bgep->phy_aux_status &
1009 998 MII_AUX_STATUS_DUPLEX_IND_5906) ? LINK_DUPLEX_FULL :
1010 999 LINK_DUPLEX_HALF;
1011 1000 }
1012 1001 } else {
1013 1002 bgep->param_link_speed = bge_copper_link_speed[mode];
1014 1003 bgep->param_link_duplex = bge_copper_link_duplex[mode];
1015 1004 }
1016 1005
1017 1006 BGE_DEBUG(("bge_check_copper: link now %s speed %d duplex %d",
1018 1007 UPORDOWN(bgep->param_link_up),
1019 1008 bgep->param_link_speed,
1020 1009 bgep->param_link_duplex));
1021 1010
1022 1011 return (B_TRUE);
1023 1012 }
1024 1013
1025 1014 static const phys_ops_t copper_ops = {
1026 1015 bge_restart_copper,
1027 1016 bge_update_copper,
1028 1017 bge_check_copper
1029 1018 };
1030 1019
1031 1020
1032 1021 /*
1033 1022 * ========== SerDes support ==========
1034 1023 */
1035 1024
1036 1025 #undef BGE_DBG
1037 1026 #define BGE_DBG BGE_DBG_SERDES /* debug flag for this code */
1038 1027
1039 1028 /*
1040 1029 * Reinitialise the SerDes interface. Note that it normally powers
1041 1030 * up in the disabled state, so we need to explicitly activate it.
1042 1031 */
1043 1032 static int
1044 1033 bge_restart_serdes(bge_t *bgep, boolean_t powerdown)
1045 1034 {
1046 1035 uint32_t macmode;
1047 1036
1048 1037 BGE_TRACE(("bge_restart_serdes($%p, %d)", (void *)bgep, powerdown));
1049 1038
1050 1039 ASSERT(mutex_owned(bgep->genlock));
1051 1040
1052 1041 /*
1053 1042 * Ensure that the main Ethernet MAC mode register is programmed
1054 1043 * appropriately for the SerDes interface ...
1055 1044 */
1056 1045 macmode = bge_reg_get32(bgep, ETHERNET_MAC_MODE_REG);
1057 1046 if (DEVICE_5714_SERIES_CHIPSETS(bgep)) {
1058 1047 macmode |= ETHERNET_MODE_LINK_POLARITY;
1059 1048 macmode &= ~ETHERNET_MODE_PORTMODE_MASK;
1060 1049 macmode |= ETHERNET_MODE_PORTMODE_GMII;
1061 1050 } else {
1062 1051 macmode &= ~ETHERNET_MODE_LINK_POLARITY;
1063 1052 macmode &= ~ETHERNET_MODE_PORTMODE_MASK;
1064 1053 macmode |= ETHERNET_MODE_PORTMODE_TBI;
1065 1054 }
1066 1055 bge_reg_put32(bgep, ETHERNET_MAC_MODE_REG, macmode);
1067 1056
1068 1057 /*
1069 1058 * Ensure that loopback is OFF and comma detection is enabled. Then
1070 1059 * disable the SerDes output (the first time through, it may/will
1071 1060 * already be disabled). If we're shutting down, leave it disabled.
1072 1061 */
1073 1062 bge_reg_clr32(bgep, SERDES_CONTROL_REG, SERDES_CONTROL_TBI_LOOPBACK);
1074 1063 bge_reg_set32(bgep, SERDES_CONTROL_REG, SERDES_CONTROL_COMMA_DETECT);
1075 1064 bge_reg_set32(bgep, SERDES_CONTROL_REG, SERDES_CONTROL_TX_DISABLE);
1076 1065 if (powerdown)
1077 1066 return (DDI_SUCCESS);
1078 1067
1079 1068 /*
1080 1069 * Otherwise, pause, (re-)enable the SerDes output, and send
1081 1070 * all-zero config words in order to force autoneg restart.
1082 1071 * Invalidate the saved "link partners received configs", as
1083 1072 * we're starting over ...
1084 1073 */
1085 1074 drv_usecwait(10000);
1086 1075 bge_reg_clr32(bgep, SERDES_CONTROL_REG, SERDES_CONTROL_TX_DISABLE);
1087 1076 bge_reg_put32(bgep, TX_1000BASEX_AUTONEG_REG, 0);
1088 1077 bge_reg_set32(bgep, ETHERNET_MAC_MODE_REG, ETHERNET_MODE_SEND_CFGS);
1089 1078 drv_usecwait(10);
1090 1079 bge_reg_clr32(bgep, ETHERNET_MAC_MODE_REG, ETHERNET_MODE_SEND_CFGS);
1091 1080 bgep->serdes_lpadv = AUTONEG_CODE_FAULT_ANEG_ERR;
1092 1081 bgep->serdes_status = ~0U;
1093 1082 return (DDI_SUCCESS);
1094 1083 }
1095 1084
1096 1085 /*
1097 1086 * Synchronise the SerDes speed/duplex/autonegotiation capabilities and
1098 1087 * advertisements with the required settings as specified by the various
1099 1088 * param_* variables that can be poked via the NDD interface.
1100 1089 *
1101 1090 * We always reinitalise the SerDes; this should cause the link to go down,
1102 1091 * and then back up again once the link is stable and autonegotiation
1103 1092 * (if enabled) is complete. We should get a link state change interrupt
1104 1093 * somewhere along the way ...
1105 1094 *
1106 1095 * NOTE: SerDes only supports 1000FDX/HDX (with or without pause) so the
1107 1096 * param_* variables relating to lower speeds are ignored.
1108 1097 *
1109 1098 * NOTE: <genlock> must already be held by the caller
1110 1099 */
1111 1100 static int
1112 1101 bge_update_serdes(bge_t *bgep)
1113 1102 {
1114 1103 boolean_t adv_autoneg;
1115 1104 boolean_t adv_pause;
1116 1105 boolean_t adv_asym_pause;
1117 1106 boolean_t adv_1000fdx;
1118 1107 boolean_t adv_1000hdx;
1119 1108
1120 1109 uint32_t serdes;
1121 1110 uint32_t advert;
1122 1111
1123 1112 BGE_TRACE(("bge_update_serdes($%p)", (void *)bgep));
1124 1113
1125 1114 ASSERT(mutex_owned(bgep->genlock));
1126 1115
1127 1116 BGE_DEBUG(("bge_update_serdes: autoneg %d "
1128 1117 "pause %d asym_pause %d "
1129 1118 "1000fdx %d 1000hdx %d "
1130 1119 "100fdx %d 100hdx %d "
1131 1120 "10fdx %d 10hdx %d ",
1132 1121 bgep->param_adv_autoneg,
1133 1122 bgep->param_adv_pause, bgep->param_adv_asym_pause,
1134 1123 bgep->param_adv_1000fdx, bgep->param_adv_1000hdx,
1135 1124 bgep->param_adv_100fdx, bgep->param_adv_100hdx,
1136 1125 bgep->param_adv_10fdx, bgep->param_adv_10hdx));
1137 1126
1138 1127 serdes = advert = 0;
1139 1128
1140 1129 /*
1141 1130 * SerDes settings are normally based on the param_* variables,
1142 1131 * but if any loopback mode is in effect, that takes precedence.
1143 1132 *
1144 1133 * BGE supports MAC-internal loopback, PHY-internal loopback,
1145 1134 * and External loopback at a variety of speeds (with a special
1146 1135 * cable). In all cases, autoneg is turned OFF, full-duplex
1147 1136 * is turned ON, and the speed/mastership is forced.
1148 1137 *
1149 1138 * Note: for the SerDes interface, "PHY" internal loopback is
1150 1139 * interpreted as SerDes internal loopback, and all external
1151 1140 * loopback modes are treated equivalently, as 1Gb/external.
1152 1141 */
1153 1142 switch (bgep->param_loop_mode) {
1154 1143 case BGE_LOOP_NONE:
1155 1144 default:
1156 1145 adv_autoneg = bgep->param_adv_autoneg;
1157 1146 adv_pause = bgep->param_adv_pause;
1158 1147 adv_asym_pause = bgep->param_adv_asym_pause;
1159 1148 adv_1000fdx = bgep->param_adv_1000fdx;
1160 1149 adv_1000hdx = bgep->param_adv_1000hdx;
1161 1150 break;
1162 1151
1163 1152 case BGE_LOOP_INTERNAL_PHY:
1164 1153 serdes |= SERDES_CONTROL_TBI_LOOPBACK;
1165 1154 /* FALLTHRU */
1166 1155 case BGE_LOOP_INTERNAL_MAC:
1167 1156 case BGE_LOOP_EXTERNAL_1000:
1168 1157 case BGE_LOOP_EXTERNAL_100:
1169 1158 case BGE_LOOP_EXTERNAL_10:
1170 1159 adv_autoneg = adv_pause = adv_asym_pause = B_FALSE;
1171 1160 adv_1000fdx = B_TRUE;
1172 1161 adv_1000hdx = B_FALSE;
1173 1162 break;
1174 1163 }
1175 1164
1176 1165 BGE_DEBUG(("bge_update_serdes: autoneg %d "
1177 1166 "pause %d asym_pause %d "
1178 1167 "1000fdx %d 1000hdx %d ",
1179 1168 adv_autoneg,
1180 1169 adv_pause, adv_asym_pause,
1181 1170 adv_1000fdx, adv_1000hdx));
1182 1171
1183 1172 /*
1184 1173 * We should have at least one gigabit technology capability
1185 1174 * set; if not, we select a default of 1000Mb/s full-duplex
1186 1175 */
1187 1176 if (!adv_1000fdx && !adv_1000hdx)
1188 1177 adv_1000fdx = B_TRUE;
1189 1178
1190 1179 /*
1191 1180 * Now transform the adv_* variables into the proper settings
1192 1181 * of the SerDes registers ...
1193 1182 *
1194 1183 * If autonegotiation is (now) not enabled, pretend it's been
1195 1184 * done and failed ...
1196 1185 */
1197 1186 if (!adv_autoneg)
1198 1187 advert |= AUTONEG_CODE_FAULT_ANEG_ERR;
1199 1188
1200 1189 if (adv_1000fdx) {
1201 1190 advert |= AUTONEG_CODE_FULL_DUPLEX;
1202 1191 bgep->param_adv_1000fdx = adv_1000fdx;
1203 1192 bgep->param_link_duplex = LINK_DUPLEX_FULL;
1204 1193 bgep->param_link_speed = 1000;
1205 1194 }
1206 1195 if (adv_1000hdx) {
1207 1196 advert |= AUTONEG_CODE_HALF_DUPLEX;
1208 1197 bgep->param_adv_1000hdx = adv_1000hdx;
1209 1198 bgep->param_link_duplex = LINK_DUPLEX_HALF;
1210 1199 bgep->param_link_speed = 1000;
1211 1200 }
1212 1201
1213 1202 if (adv_pause)
1214 1203 advert |= AUTONEG_CODE_PAUSE;
1215 1204 if (adv_asym_pause)
1216 1205 advert |= AUTONEG_CODE_ASYM_PAUSE;
1217 1206
1218 1207 /*
1219 1208 * Restart the SerDes and write the new values. Note the
1220 1209 * time, so that we can say whether subsequent link state
1221 1210 * changes can be attributed to our reprogramming the SerDes
1222 1211 */
1223 1212 bgep->serdes_advert = advert;
1224 1213 (void) bge_restart_serdes(bgep, B_FALSE);
1225 1214 bge_reg_set32(bgep, SERDES_CONTROL_REG, serdes);
1226 1215
1227 1216 BGE_DEBUG(("bge_update_serdes: serdes |= 0x%x, advert 0x%x",
1228 1217 serdes, advert));
1229 1218 return (DDI_SUCCESS);
1230 1219 }
1231 1220
1232 1221 /*
1233 1222 * Bare-minimum autoneg protocol
1234 1223 *
1235 1224 * This code is only called when the link is up and we're receiving config
1236 1225 * words, which implies that the link partner wants to autonegotiate
1237 1226 * (otherwise, we wouldn't see configs and wouldn't reach this code).
1238 1227 */
1239 1228 static void
1240 1229 bge_autoneg_serdes(bge_t *bgep)
1241 1230 {
1242 1231 boolean_t ack;
1243 1232
1244 1233 bgep->serdes_lpadv = bge_reg_get32(bgep, RX_1000BASEX_AUTONEG_REG);
1245 1234 ack = BIS(bgep->serdes_lpadv, AUTONEG_CODE_ACKNOWLEDGE);
1246 1235
1247 1236 if (!ack) {
1248 1237 /*
1249 1238 * Phase 1: after SerDes reset, we send a few zero configs
1250 1239 * but then stop. Here the partner is sending configs, but
1251 1240 * not ACKing ours; we assume that's 'cos we're not sending
1252 1241 * any. So here we send ours, with ACK already set.
1253 1242 */
1254 1243 bge_reg_put32(bgep, TX_1000BASEX_AUTONEG_REG,
1255 1244 bgep->serdes_advert | AUTONEG_CODE_ACKNOWLEDGE);
1256 1245 bge_reg_set32(bgep, ETHERNET_MAC_MODE_REG,
1257 1246 ETHERNET_MODE_SEND_CFGS);
1258 1247 } else {
1259 1248 /*
1260 1249 * Phase 2: partner has ACKed our configs, so now we can
1261 1250 * stop sending; once our partner also stops sending, we
1262 1251 * can resolve the Tx/Rx configs.
1263 1252 */
1264 1253 bge_reg_clr32(bgep, ETHERNET_MAC_MODE_REG,
1265 1254 ETHERNET_MODE_SEND_CFGS);
1266 1255 }
1267 1256
1268 1257 BGE_DEBUG(("bge_autoneg_serdes: Rx 0x%x %s Tx 0x%x",
1269 1258 bgep->serdes_lpadv,
1270 1259 ack ? "stop" : "send",
1271 1260 bgep->serdes_advert));
1272 1261 }
1273 1262
1274 1263 static boolean_t
1275 1264 bge_check_serdes(bge_t *bgep, boolean_t recheck)
1276 1265 {
1277 1266 uint32_t emac_status;
1278 1267 uint32_t tx_status;
1279 1268 uint32_t lpadv;
1280 1269 boolean_t linkup;
1281 1270 boolean_t linkup_old = bgep->param_link_up;
1282 1271
1283 1272 for (;;) {
1284 1273 /*
1285 1274 * Step 10: BCM5714S, BCM5715S only
1286 1275 * Don't call function bge_autoneg_serdes() as
1287 1276 * RX_1000BASEX_AUTONEG_REG (0x0448) is not applicable
1288 1277 * to BCM5705, BCM5788, BCM5721, BCM5751, BCM5752,
1289 1278 * BCM5714, and BCM5715 devices.
1290 1279 */
1291 1280 if (DEVICE_5714_SERIES_CHIPSETS(bgep)) {
1292 1281 tx_status = bge_reg_get32(bgep,
1293 1282 TRANSMIT_MAC_STATUS_REG);
1294 1283 linkup = BIS(tx_status, TRANSMIT_STATUS_LINK_UP);
1295 1284 emac_status = bge_reg_get32(bgep,
1296 1285 ETHERNET_MAC_STATUS_REG);
1297 1286 bgep->serdes_status = emac_status;
1298 1287 if ((linkup && linkup_old) ||
1299 1288 (!linkup && !linkup_old)) {
1300 1289 emac_status &= ~ETHERNET_STATUS_LINK_CHANGED;
1301 1290 emac_status &= ~ETHERNET_STATUS_RECEIVING_CFG;
1302 1291 break;
1303 1292 }
1304 1293 emac_status |= ETHERNET_STATUS_LINK_CHANGED;
1305 1294 emac_status |= ETHERNET_STATUS_RECEIVING_CFG;
1306 1295 if (linkup)
1307 1296 linkup_old = B_TRUE;
1308 1297 else
1309 1298 linkup_old = B_FALSE;
1310 1299 recheck = B_TRUE;
1311 1300 } else {
1312 1301 /*
1313 1302 * Step 10: others
1314 1303 * read & clear the main (Ethernet) MAC status
1315 1304 * (the relevant bits of this are write-one-to-clear).
1316 1305 */
1317 1306 emac_status = bge_reg_get32(bgep,
1318 1307 ETHERNET_MAC_STATUS_REG);
1319 1308 bge_reg_put32(bgep,
1320 1309 ETHERNET_MAC_STATUS_REG, emac_status);
1321 1310
1322 1311 BGE_DEBUG(("bge_check_serdes: link %d/%s, "
1323 1312 "MAC status 0x%x (was 0x%x)",
1324 1313 bgep->link_state, UPORDOWN(bgep->param_link_up),
1325 1314 emac_status, bgep->serdes_status));
1326 1315
1327 1316 /*
1328 1317 * We will only consider the link UP if all the readings
1329 1318 * are consistent and give meaningful results ...
1330 1319 */
1331 1320 bgep->serdes_status = emac_status;
1332 1321 linkup = BIS(emac_status,
1333 1322 ETHERNET_STATUS_SIGNAL_DETECT);
1334 1323 linkup &= BIS(emac_status, ETHERNET_STATUS_PCS_SYNCHED);
1335 1324
1336 1325 /*
1337 1326 * Now some fiddling with the interpretation:
1338 1327 * if there's been an error at the PCS level, treat
1339 1328 * it as a link change (the h/w doesn't do this)
1340 1329 *
1341 1330 * if there's been a change, but it's only a PCS
1342 1331 * sync change (not a config change), AND the link
1343 1332 * already was & is still UP, then ignore the
1344 1333 * change
1345 1334 */
1346 1335 if (BIS(emac_status, ETHERNET_STATUS_PCS_ERROR))
1347 1336 emac_status |= ETHERNET_STATUS_LINK_CHANGED;
1348 1337 else if (BIC(emac_status, ETHERNET_STATUS_CFG_CHANGED))
1349 1338 if (bgep->param_link_up && linkup)
1350 1339 emac_status &=
1351 1340 ~ETHERNET_STATUS_LINK_CHANGED;
1352 1341
1353 1342 BGE_DEBUG(("bge_check_serdes: status 0x%x => 0x%x %s",
1354 1343 bgep->serdes_status, emac_status,
1355 1344 UPORDOWN(linkup)));
1356 1345
1357 1346 /*
1358 1347 * If we're receiving configs, run the autoneg protocol
1359 1348 */
1360 1349 if (linkup && BIS(emac_status,
1361 1350 ETHERNET_STATUS_RECEIVING_CFG))
1362 1351 bge_autoneg_serdes(bgep);
1363 1352
1364 1353 /*
1365 1354 * If the SerDes status hasn't changed, we're done ...
1366 1355 */
1367 1356 if (BIC(emac_status, ETHERNET_STATUS_LINK_CHANGED))
1368 1357 break;
1369 1358
1370 1359 /*
1371 1360 * Go round again until we no longer see a change ...
1372 1361 */
1373 1362 recheck = B_TRUE;
1374 1363 }
1375 1364 }
1376 1365
1377 1366 /*
1378 1367 * If we're not forcing a recheck (i.e. the link state was already
1379 1368 * known), and we didn't see the hardware flag a change, there's
1380 1369 * no more to do (and we tell the caller nothing happened).
1381 1370 */
1382 1371 if (!recheck)
1383 1372 return (B_FALSE);
1384 1373
1385 1374 /*
1386 1375 * Don't resolve autoneg until we're no longer receiving configs
1387 1376 */
1388 1377 if (linkup && BIS(emac_status, ETHERNET_STATUS_RECEIVING_CFG))
1389 1378 return (B_FALSE);
1390 1379
1391 1380 /*
1392 1381 * Assume very little ...
1393 1382 */
1394 1383 bgep->param_lp_autoneg = B_FALSE;
1395 1384 bgep->param_lp_1000fdx = B_FALSE;
1396 1385 bgep->param_lp_1000hdx = B_FALSE;
1397 1386 bgep->param_lp_100fdx = B_FALSE;
1398 1387 bgep->param_lp_100hdx = B_FALSE;
1399 1388 bgep->param_lp_10fdx = B_FALSE;
1400 1389 bgep->param_lp_10hdx = B_FALSE;
1401 1390 bgep->param_lp_pause = B_FALSE;
1402 1391 bgep->param_lp_asym_pause = B_FALSE;
1403 1392 bgep->param_link_autoneg = B_FALSE;
1404 1393 bgep->param_link_tx_pause = B_FALSE;
1405 1394 if (bgep->param_adv_autoneg)
1406 1395 bgep->param_link_rx_pause = B_FALSE;
1407 1396 else
1408 1397 bgep->param_link_rx_pause = bgep->param_adv_pause;
1409 1398
1410 1399 /*
1411 1400 * Discover all the link partner's abilities.
1412 1401 */
1413 1402 lpadv = bgep->serdes_lpadv;
1414 1403 if (lpadv != 0 && BIC(lpadv, AUTONEG_CODE_FAULT_MASK)) {
1415 1404 /*
1416 1405 * No fault, so derive partner's capabilities
1417 1406 */
1418 1407 bgep->param_lp_autoneg = B_TRUE;
1419 1408 bgep->param_lp_1000fdx = BIS(lpadv, AUTONEG_CODE_FULL_DUPLEX);
1420 1409 bgep->param_lp_1000hdx = BIS(lpadv, AUTONEG_CODE_HALF_DUPLEX);
1421 1410 bgep->param_lp_pause = BIS(lpadv, AUTONEG_CODE_PAUSE);
1422 1411 bgep->param_lp_asym_pause = BIS(lpadv, AUTONEG_CODE_ASYM_PAUSE);
1423 1412
1424 1413 /*
1425 1414 * Pause direction resolution
1426 1415 */
1427 1416 bgep->param_link_autoneg = B_TRUE;
1428 1417 if (bgep->param_adv_pause &&
1429 1418 bgep->param_lp_pause) {
1430 1419 bgep->param_link_tx_pause = B_TRUE;
1431 1420 bgep->param_link_rx_pause = B_TRUE;
1432 1421 }
1433 1422 if (bgep->param_adv_asym_pause &&
1434 1423 bgep->param_lp_asym_pause) {
1435 1424 if (bgep->param_adv_pause)
1436 1425 bgep->param_link_rx_pause = B_TRUE;
1437 1426 if (bgep->param_lp_pause)
1438 1427 bgep->param_link_tx_pause = B_TRUE;
1439 1428 }
1440 1429 }
1441 1430
1442 1431 /*
1443 1432 * Step 12: update ndd-visible state parameters, BUT!
1444 1433 * we don't transfer the new state to <link_state> just yet;
1445 1434 * instead we mark the <link_state> as UNKNOWN, and our caller
1446 1435 * will resolve it once the status has stopped changing and
1447 1436 * been stable for several seconds.
1448 1437 */
1449 1438 BGE_DEBUG(("bge_check_serdes: link was %s speed %d duplex %d",
1450 1439 UPORDOWN(bgep->param_link_up),
1451 1440 bgep->param_link_speed,
1452 1441 bgep->param_link_duplex));
1453 1442
1454 1443 if (linkup) {
1455 1444 bgep->param_link_up = B_TRUE;
1456 1445 bgep->param_link_speed = 1000;
1457 1446 if (bgep->param_adv_1000fdx)
1458 1447 bgep->param_link_duplex = LINK_DUPLEX_FULL;
1459 1448 else
1460 1449 bgep->param_link_duplex = LINK_DUPLEX_HALF;
1461 1450 if (bgep->param_lp_autoneg && !bgep->param_lp_1000fdx)
1462 1451 bgep->param_link_duplex = LINK_DUPLEX_HALF;
1463 1452 } else {
1464 1453 bgep->param_link_up = B_FALSE;
1465 1454 bgep->param_link_speed = 0;
1466 1455 bgep->param_link_duplex = LINK_DUPLEX_UNKNOWN;
1467 1456 }
1468 1457 bgep->link_state = LINK_STATE_UNKNOWN;
1469 1458
1470 1459 BGE_DEBUG(("bge_check_serdes: link now %s speed %d duplex %d",
1471 1460 UPORDOWN(bgep->param_link_up),
1472 1461 bgep->param_link_speed,
1473 1462 bgep->param_link_duplex));
1474 1463
1475 1464 return (B_TRUE);
1476 1465 }
1477 1466
1478 1467 static const phys_ops_t serdes_ops = {
1479 1468 bge_restart_serdes,
1480 1469 bge_update_serdes,
1481 1470 bge_check_serdes
1482 1471 };
1483 1472
1484 1473 /*
1485 1474 * ========== Exported physical layer control routines ==========
1486 1475 */
1487 1476
1488 1477 #undef BGE_DBG
1489 1478 #define BGE_DBG BGE_DBG_PHYS /* debug flag for this code */
1490 1479
1491 1480 /*
1492 1481 * Here we have to determine which media we're using (copper or serdes).
1493 1482 * Once that's done, we can initialise the physical layer appropriately.
1494 1483 */
1495 1484 int
1496 1485 bge_phys_init(bge_t *bgep)
1497 1486 {
1498 1487 BGE_TRACE(("bge_phys_init($%p)", (void *)bgep));
1499 1488
|
↓ open down ↓ |
896 lines elided |
↑ open up ↑ |
1500 1489 mutex_enter(bgep->genlock);
1501 1490
1502 1491 /*
1503 1492 * Probe for the (internal) PHY. If it's not there, we'll assume
1504 1493 * that this is a 5703/4S, with a SerDes interface rather than
1505 1494 * a PHY. BCM5714S/BCM5715S are not supported.It are based on
1506 1495 * BCM800x PHY.
1507 1496 */
1508 1497 bgep->phy_mii_addr = 1;
1509 1498 if (DEVICE_5717_SERIES_CHIPSETS(bgep)) {
1510 - int regval = bge_reg_get32(bgep, CPMU_STATUS_REG);
1511 - if (regval & CPMU_STATUS_FUN_NUM)
1512 - bgep->phy_mii_addr += 1;
1499 + uint32_t regval = bge_reg_get32(bgep, CPMU_STATUS_REG);
1500 + if (MHCR_CHIP_ASIC_REV(bgep->chipid.asic_rev) ==
1501 + MHCR_CHIP_ASIC_REV_5719 ||
1502 + MHCR_CHIP_ASIC_REV(bgep->chipid.asic_rev) ==
1503 + MHCR_CHIP_ASIC_REV_5720) {
1504 + bgep->phy_mii_addr +=
1505 + (regval & CPMU_STATUS_FUN_NUM_5719) >>
1506 + CPMU_STATUS_FUN_NUM_5719_SHIFT;
1507 + } else {
1508 + bgep->phy_mii_addr +=
1509 + (regval & CPMU_STATUS_FUN_NUM_5717) ? 1 : 0;
1510 + }
1513 1511 regval = bge_reg_get32(bgep, SGMII_STATUS_REG);
1514 1512 if (regval & MEDIA_SELECTION_MODE)
1515 1513 bgep->phy_mii_addr += 7;
1516 1514 }
1517 -
1518 1515 if (bge_phy_probe(bgep)) {
1519 1516 bgep->chipid.flags &= ~CHIP_FLAG_SERDES;
1520 1517 bgep->physops = &copper_ops;
1521 1518 } else {
1522 1519 bgep->chipid.flags |= CHIP_FLAG_SERDES;
1523 1520 bgep->physops = &serdes_ops;
1524 1521 }
1525 1522
1526 1523 if ((*bgep->physops->phys_restart)(bgep, B_FALSE) != DDI_SUCCESS) {
1527 1524 mutex_exit(bgep->genlock);
1528 1525 return (EIO);
1529 1526 }
1530 1527 if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK) {
1531 1528 mutex_exit(bgep->genlock);
1532 1529 return (EIO);
1533 1530 }
1534 1531 mutex_exit(bgep->genlock);
1535 1532 return (0);
1536 1533 }
1537 1534
1538 1535 /*
1539 1536 * Reset the physical layer
1540 1537 */
1541 1538 void
1542 1539 bge_phys_reset(bge_t *bgep)
1543 1540 {
1544 1541 BGE_TRACE(("bge_phys_reset($%p)", (void *)bgep));
1545 1542
1546 1543 mutex_enter(bgep->genlock);
1547 1544 if ((*bgep->physops->phys_restart)(bgep, B_FALSE) != DDI_SUCCESS)
1548 1545 ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_UNAFFECTED);
1549 1546 if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK)
1550 1547 ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_UNAFFECTED);
1551 1548 mutex_exit(bgep->genlock);
1552 1549 }
1553 1550
1554 1551 /*
1555 1552 * Reset and power off the physical layer.
1556 1553 *
1557 1554 * Another RESET should get it back to working, but it may take a few
1558 1555 * seconds it may take a few moments to return to normal operation ...
1559 1556 */
1560 1557 int
1561 1558 bge_phys_idle(bge_t *bgep)
1562 1559 {
1563 1560 BGE_TRACE(("bge_phys_idle($%p)", (void *)bgep));
1564 1561
1565 1562 ASSERT(mutex_owned(bgep->genlock));
1566 1563 return ((*bgep->physops->phys_restart)(bgep, B_TRUE));
1567 1564 }
1568 1565
1569 1566 /*
1570 1567 * Synchronise the PHYSICAL layer's speed/duplex/autonegotiation capabilities
1571 1568 * and advertisements with the required settings as specified by the various
1572 1569 * param_* variables that can be poked via the NDD interface.
1573 1570 *
1574 1571 * We always reset the PHYSICAL layer and reprogram *all* relevant registers.
1575 1572 * This is expected to cause the link to go down, and then back up again once
1576 1573 * the link is stable and autonegotiation (if enabled) is complete. We should
1577 1574 * get a link state change interrupt somewhere along the way ...
1578 1575 *
1579 1576 * NOTE: <genlock> must already be held by the caller
1580 1577 */
1581 1578 int
1582 1579 bge_phys_update(bge_t *bgep)
1583 1580 {
1584 1581 BGE_TRACE(("bge_phys_update($%p)", (void *)bgep));
1585 1582
1586 1583 ASSERT(mutex_owned(bgep->genlock));
1587 1584 return ((*bgep->physops->phys_update)(bgep));
1588 1585 }
1589 1586
1590 1587 #undef BGE_DBG
1591 1588 #define BGE_DBG BGE_DBG_LINK /* debug flag for this code */
1592 1589
1593 1590 /*
1594 1591 * Read the link status and determine whether anything's changed ...
1595 1592 *
1596 1593 * This routine should be called whenever the chip flags a change
1597 1594 * in the hardware link state.
1598 1595 *
1599 1596 * This routine returns B_FALSE if the link state has not changed,
1600 1597 * returns B_TRUE when the change to the new state should be accepted.
1601 1598 * In such a case, the param_* variables give the new hardware state,
1602 1599 * which the caller should use to update link_state etc.
1603 1600 *
1604 1601 * The caller must already hold <genlock>
1605 1602 */
1606 1603 boolean_t
1607 1604 bge_phys_check(bge_t *bgep)
1608 1605 {
1609 1606 int32_t orig_state;
1610 1607 boolean_t recheck;
1611 1608
1612 1609 BGE_TRACE(("bge_phys_check($%p)", (void *)bgep));
1613 1610
1614 1611 ASSERT(mutex_owned(bgep->genlock));
1615 1612
1616 1613 orig_state = bgep->link_state;
1617 1614 recheck = orig_state == LINK_STATE_UNKNOWN;
1618 1615 recheck = (*bgep->physops->phys_check)(bgep, recheck);
1619 1616 if (!recheck)
1620 1617 return (B_FALSE);
1621 1618
1622 1619 return (B_TRUE);
1623 1620 }
|
↓ open down ↓ |
96 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX