6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 #include "bge_impl.h"
27
28 /*
29 * Bit test macros, returning boolean_t values
30 */
31 #define BIS(w, b) (((w) & (b)) ? B_TRUE : B_FALSE)
32 #define BIC(w, b) (((w) & (b)) ? B_FALSE : B_TRUE)
33 #define UPORDOWN(x) ((x) ? "up" : "down")
34
35 /*
36 * ========== Copper (PHY) support ==========
37 */
38
39 #define BGE_DBG BGE_DBG_PHY /* debug flag for this code */
40
41 /*
42 * #defines:
43 * BGE_COPPER_WIRESPEED controls whether the Broadcom WireSpeed(tm)
44 * feature is enabled. We need to recheck whether this can be
45 * enabled; at one time it seemed to interact unpleasantly with the
190 case 0xffff:
191 return (B_FALSE);
192
193 default :
194 return (B_TRUE);
195 }
196 }
197 }
198
199 /*
200 * Basic low-level function to reset the PHY.
201 * Doesn't incorporate any special-case workarounds.
202 *
203 * Returns TRUE on success, FALSE if the RESET bit doesn't clear
204 */
205 static boolean_t
206 bge_phy_reset(bge_t *bgep)
207 {
208 uint16_t control;
209 uint_t count;
210
211 BGE_TRACE(("bge_phy_reset($%p)", (void *)bgep));
212
213 ASSERT(mutex_owned(bgep->genlock));
214
215 if (DEVICE_5906_SERIES_CHIPSETS(bgep)) {
216 drv_usecwait(40);
217 /* put PHY into ready state */
218 bge_reg_clr32(bgep, MISC_CONFIG_REG, MISC_CONFIG_EPHY_IDDQ);
219 (void) bge_reg_get32(bgep, MISC_CONFIG_REG); /* flush */
220 drv_usecwait(40);
221 }
222
223 /*
224 * Set the PHY RESET bit, then wait up to 5 ms for it to self-clear
225 */
226 bge_mii_put16(bgep, MII_CONTROL, MII_CONTROL_RESET);
227 for (count = 0; ++count < 1000; ) {
228 drv_usecwait(5);
229 control = bge_mii_get16(bgep, MII_CONTROL);
230 if (BIC(control, MII_CONTROL_RESET))
231 return (B_TRUE);
232 }
233
234 if (DEVICE_5906_SERIES_CHIPSETS(bgep))
235 (void) bge_adj_volt_5906(bgep);
236
237 BGE_DEBUG(("bge_phy_reset: FAILED, control now 0x%x", control));
238
239 return (B_FALSE);
240 }
241
242 /*
243 * Basic low-level function to powerdown the PHY, if supported
244 * If powerdown support is compiled out, this function does nothing.
245 */
246 static void
247 bge_phy_powerdown(bge_t *bgep)
248 {
249 BGE_TRACE(("bge_phy_powerdown"));
250 #if BGE_COPPER_IDLEOFF
251 bge_mii_put16(bgep, MII_CONTROL, MII_CONTROL_PWRDN);
252 #endif /* BGE_COPPER_IDLEOFF */
253 }
254
255 /*
256 * The following functions are based on sample code provided by
257 * Broadcom (20-June-2003), and implement workarounds said to be
258 * required on the early revisions of the BCM5703/4C.
259 *
524 bge_mii_put16(bgep, 0x17, 0x401f);
525 bge_mii_put16(bgep, 0x15, 0x14e2);
526 bge_mii_put16(bgep, 0x18, 0x0400);
527 }
528
529 /*
530 * End of Broadcom-derived workaround code *
531 */
532
533 static int
534 bge_restart_copper(bge_t *bgep, boolean_t powerdown)
535 {
536 uint16_t phy_status;
537 boolean_t reset_ok;
538 uint16_t extctrl, auxctrl;
539
540 BGE_TRACE(("bge_restart_copper($%p, %d)", (void *)bgep, powerdown));
541
542 ASSERT(mutex_owned(bgep->genlock));
543
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 */
567 reset_ok = bge_phy_reset(bgep);
568 if (!reset_ok)
569 bge_fm_ereport(bgep, DDI_FM_DEVICE_NO_RESPONSE);
570 break;
571 }
572 if (!reset_ok) {
573 BGE_REPORT((bgep, "PHY failed to reset correctly"));
574 return (DDI_FAILURE);
575 }
576
577 /*
578 * Step 5: disable WOL (not required after RESET)
579 *
580 * Step 6: refer to errata
581 */
582 switch (bgep->chipid.asic_rev) {
583 default:
584 break;
585
586 case MHCR_CHIP_REV_5704_A0:
587 bge_phy_tweak_gmii(bgep);
588 break;
589 }
590
591 switch (MHCR_CHIP_ASIC_REV(bgep->chipid.asic_rev)) {
592 case MHCR_CHIP_ASIC_REV_5705:
593 case MHCR_CHIP_ASIC_REV_5721_5751:
594 bge_phy_bit_err_fix(bgep);
595 break;
596 }
597
598 if (!(bgep->chipid.flags & CHIP_FLAG_NO_JUMBO) &&
599 (bgep->chipid.default_mtu > BGE_DEFAULT_MTU)) {
600 /* Set the GMII Fifo Elasticity to high latency */
601 extctrl = bge_mii_get16(bgep, 0x10);
602 bge_mii_put16(bgep, 0x10, extctrl | 0x1);
603
604 /* Allow reception of extended length packets */
605 bge_mii_put16(bgep, MII_AUX_CONTROL, 0x0007);
606 auxctrl = bge_mii_get16(bgep, MII_AUX_CONTROL);
607 auxctrl |= 0x4000;
608 bge_mii_put16(bgep, MII_AUX_CONTROL, auxctrl);
609 }
610
611 /*
612 * Step 7: read the MII_INTR_STATUS register twice,
613 * in order to clear any sticky bits (but they should
1490
1491 /*
1492 * Here we have to determine which media we're using (copper or serdes).
1493 * Once that's done, we can initialise the physical layer appropriately.
1494 */
1495 int
1496 bge_phys_init(bge_t *bgep)
1497 {
1498 BGE_TRACE(("bge_phys_init($%p)", (void *)bgep));
1499
1500 mutex_enter(bgep->genlock);
1501
1502 /*
1503 * Probe for the (internal) PHY. If it's not there, we'll assume
1504 * that this is a 5703/4S, with a SerDes interface rather than
1505 * a PHY. BCM5714S/BCM5715S are not supported.It are based on
1506 * BCM800x PHY.
1507 */
1508 bgep->phy_mii_addr = 1;
1509 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;
1513 regval = bge_reg_get32(bgep, SGMII_STATUS_REG);
1514 if (regval & MEDIA_SELECTION_MODE)
1515 bgep->phy_mii_addr += 7;
1516 }
1517
1518 if (bge_phy_probe(bgep)) {
1519 bgep->chipid.flags &= ~CHIP_FLAG_SERDES;
1520 bgep->physops = &copper_ops;
1521 } else {
1522 bgep->chipid.flags |= CHIP_FLAG_SERDES;
1523 bgep->physops = &serdes_ops;
1524 }
1525
1526 if ((*bgep->physops->phys_restart)(bgep, B_FALSE) != DDI_SUCCESS) {
1527 mutex_exit(bgep->genlock);
1528 return (EIO);
1529 }
1530 if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK) {
1531 mutex_exit(bgep->genlock);
1532 return (EIO);
1533 }
1534 mutex_exit(bgep->genlock);
1535 return (0);
1536 }
1537
|
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
28 */
29
30 #include "bge_impl.h"
31
32 /*
33 * Bit test macros, returning boolean_t values
34 */
35 #define BIS(w, b) (((w) & (b)) ? B_TRUE : B_FALSE)
36 #define BIC(w, b) (((w) & (b)) ? B_FALSE : B_TRUE)
37 #define UPORDOWN(x) ((x) ? "up" : "down")
38
39 /*
40 * ========== Copper (PHY) support ==========
41 */
42
43 #define BGE_DBG BGE_DBG_PHY /* debug flag for this code */
44
45 /*
46 * #defines:
47 * BGE_COPPER_WIRESPEED controls whether the Broadcom WireSpeed(tm)
48 * feature is enabled. We need to recheck whether this can be
49 * enabled; at one time it seemed to interact unpleasantly with the
194 case 0xffff:
195 return (B_FALSE);
196
197 default :
198 return (B_TRUE);
199 }
200 }
201 }
202
203 /*
204 * Basic low-level function to reset the PHY.
205 * Doesn't incorporate any special-case workarounds.
206 *
207 * Returns TRUE on success, FALSE if the RESET bit doesn't clear
208 */
209 static boolean_t
210 bge_phy_reset(bge_t *bgep)
211 {
212 uint16_t control;
213 uint_t count;
214 boolean_t ret = B_FALSE;
215
216 BGE_TRACE(("bge_phy_reset($%p)", (void *)bgep));
217
218 ASSERT(mutex_owned(bgep->genlock));
219
220 if (DEVICE_5906_SERIES_CHIPSETS(bgep)) {
221 drv_usecwait(40);
222 /* put PHY into ready state */
223 bge_reg_clr32(bgep, MISC_CONFIG_REG, MISC_CONFIG_EPHY_IDDQ);
224 (void) bge_reg_get32(bgep, MISC_CONFIG_REG); /* flush */
225 drv_usecwait(40);
226 }
227
228 /*
229 * Set the PHY RESET bit, then wait up to 50 ms for it to self-clear
230 */
231 bge_mii_put16(bgep, MII_CONTROL, MII_CONTROL_RESET);
232 for (count = 0; ++count < 5000; ) {
233 control = bge_mii_get16(bgep, MII_CONTROL);
234 if (BIC(control, MII_CONTROL_RESET)) {
235 drv_usecwait(40);
236 ret = B_TRUE;
237 break;
238 }
239 drv_usecwait(10);
240 }
241
242 if (ret == B_TRUE && DEVICE_5906_SERIES_CHIPSETS(bgep))
243 (void) bge_adj_volt_5906(bgep);
244
245 if (ret == B_FALSE)
246 BGE_DEBUG(("bge_phy_reset: FAILED, control now 0x%x", control));
247
248 return (ret);
249 }
250
251 /*
252 * Basic low-level function to powerdown the PHY, if supported
253 * If powerdown support is compiled out, this function does nothing.
254 */
255 static void
256 bge_phy_powerdown(bge_t *bgep)
257 {
258 BGE_TRACE(("bge_phy_powerdown"));
259 #if BGE_COPPER_IDLEOFF
260 bge_mii_put16(bgep, MII_CONTROL, MII_CONTROL_PWRDN);
261 #endif /* BGE_COPPER_IDLEOFF */
262 }
263
264 /*
265 * The following functions are based on sample code provided by
266 * Broadcom (20-June-2003), and implement workarounds said to be
267 * required on the early revisions of the BCM5703/4C.
268 *
533 bge_mii_put16(bgep, 0x17, 0x401f);
534 bge_mii_put16(bgep, 0x15, 0x14e2);
535 bge_mii_put16(bgep, 0x18, 0x0400);
536 }
537
538 /*
539 * End of Broadcom-derived workaround code *
540 */
541
542 static int
543 bge_restart_copper(bge_t *bgep, boolean_t powerdown)
544 {
545 uint16_t phy_status;
546 boolean_t reset_ok;
547 uint16_t extctrl, auxctrl;
548
549 BGE_TRACE(("bge_restart_copper($%p, %d)", (void *)bgep, powerdown));
550
551 ASSERT(mutex_owned(bgep->genlock));
552
553 if (bgep->chipid.flags & CHIP_FLAG_NO_CHECK_RESET) {
554 reset_ok = bge_phy_reset(bgep);
555 if (!reset_ok)
556 bge_fm_ereport(bgep, DDI_FM_DEVICE_NO_RESPONSE);
557 } else {
558 reset_ok = bge_phy_reset_and_check(bgep);
559 }
560
561 if (!reset_ok) {
562 BGE_REPORT((bgep, "PHY failed to reset correctly"));
563 return (DDI_FAILURE);
564 }
565
566 /*
567 * Step 5: disable WOL (not required after RESET)
568 *
569 * Step 6: refer to errata
570 */
571 switch (bgep->chipid.asic_rev) {
572 default:
573 break;
574
575 case MHCR_CHIP_REV_5704_A0:
576 bge_phy_tweak_gmii(bgep);
577 break;
578 }
579
580 switch (MHCR_CHIP_ASIC_REV(bgep->chipid.asic_rev)) {
581 case MHCR_CHIP_ASIC_REV_5705:
582 case MHCR_CHIP_ASIC_REV_5750:
583 bge_phy_bit_err_fix(bgep);
584 break;
585 }
586
587 if (!(bgep->chipid.flags & CHIP_FLAG_NO_JUMBO) &&
588 (bgep->chipid.default_mtu > BGE_DEFAULT_MTU)) {
589 /* Set the GMII Fifo Elasticity to high latency */
590 extctrl = bge_mii_get16(bgep, 0x10);
591 bge_mii_put16(bgep, 0x10, extctrl | 0x1);
592
593 /* Allow reception of extended length packets */
594 bge_mii_put16(bgep, MII_AUX_CONTROL, 0x0007);
595 auxctrl = bge_mii_get16(bgep, MII_AUX_CONTROL);
596 auxctrl |= 0x4000;
597 bge_mii_put16(bgep, MII_AUX_CONTROL, auxctrl);
598 }
599
600 /*
601 * Step 7: read the MII_INTR_STATUS register twice,
602 * in order to clear any sticky bits (but they should
1479
1480 /*
1481 * Here we have to determine which media we're using (copper or serdes).
1482 * Once that's done, we can initialise the physical layer appropriately.
1483 */
1484 int
1485 bge_phys_init(bge_t *bgep)
1486 {
1487 BGE_TRACE(("bge_phys_init($%p)", (void *)bgep));
1488
1489 mutex_enter(bgep->genlock);
1490
1491 /*
1492 * Probe for the (internal) PHY. If it's not there, we'll assume
1493 * that this is a 5703/4S, with a SerDes interface rather than
1494 * a PHY. BCM5714S/BCM5715S are not supported.It are based on
1495 * BCM800x PHY.
1496 */
1497 bgep->phy_mii_addr = 1;
1498 if (DEVICE_5717_SERIES_CHIPSETS(bgep)) {
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 }
1511 regval = bge_reg_get32(bgep, SGMII_STATUS_REG);
1512 if (regval & MEDIA_SELECTION_MODE)
1513 bgep->phy_mii_addr += 7;
1514 }
1515 if (bge_phy_probe(bgep)) {
1516 bgep->chipid.flags &= ~CHIP_FLAG_SERDES;
1517 bgep->physops = &copper_ops;
1518 } else {
1519 bgep->chipid.flags |= CHIP_FLAG_SERDES;
1520 bgep->physops = &serdes_ops;
1521 }
1522
1523 if ((*bgep->physops->phys_restart)(bgep, B_FALSE) != DDI_SUCCESS) {
1524 mutex_exit(bgep->genlock);
1525 return (EIO);
1526 }
1527 if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK) {
1528 mutex_exit(bgep->genlock);
1529 return (EIO);
1530 }
1531 mutex_exit(bgep->genlock);
1532 return (0);
1533 }
1534
|