Selaa lähdekoodia

[tg3] Add support for SerDes PHY initialization

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Joseph Wong 6 vuotta sitten
vanhempi
commit
08db2fd55c
2 muutettua tiedostoa jossa 1021 lisäystä ja 4 poistoa
  1. 56
    0
      src/drivers/net/tg3/tg3.h
  2. 965
    4
      src/drivers/net/tg3/tg3_phy.c

+ 56
- 0
src/drivers/net/tg3/tg3.h Näytä tiedosto

@@ -34,6 +34,13 @@
34 34
 #define ADVERTISED_Autoneg              (1 << 6)
35 35
 /* </ethtool.h> */
36 36
 
37
+#ifndef ADVERTISED_Pause
38
+#define ADVERTISED_Pause                (1 << 13)
39
+#endif
40
+#ifndef ADVERTISED_Asym_Pause
41
+#define ADVERTISED_Asym_Pause           (1 << 14)
42
+#endif
43
+
37 44
 /* mdio.h: */
38 45
 #define MDIO_AN_EEE_ADV		60      /* EEE advertisement */
39 46
 
@@ -139,9 +146,15 @@
139 146
 #define SPEED_10			10
140 147
 #define SPEED_100			100
141 148
 #define SPEED_1000			1000
149
+#ifndef SPEED_UNKNOWN
150
+#define SPEED_UNKNOWN                   -1
151
+#endif
142 152
 
143 153
 #define DUPLEX_HALF			0x00
144 154
 #define DUPLEX_FULL			0x01
155
+#ifndef DUPLEX_UNKNOWN
156
+#define DUPLEX_UNKNOWN                  0xff
157
+#endif
145 158
 
146 159
 #define TG3_64BIT_REG_HIGH		0x00UL
147 160
 #define TG3_64BIT_REG_LOW		0x04UL
@@ -2425,6 +2438,14 @@
2425 2438
 #define MII_TG3_FET_SHDW_AUXSTAT2	0x1b
2426 2439
 #define  MII_TG3_FET_SHDW_AUXSTAT2_APD	0x0020
2427 2440
 
2441
+/* Serdes PHY Register Definitions */
2442
+#define SERDES_TG3_1000X_STATUS         0x14
2443
+#define SERDES_TG3_SGMII_MODE           0x0001
2444
+#define SERDES_TG3_LINK_UP              0x0002
2445
+#define SERDES_TG3_FULL_DUPLEX          0x0004
2446
+#define SERDES_TG3_SPEED_100            0x0008
2447
+#define SERDES_TG3_SPEED_1000           0x0010
2448
+
2428 2449
 
2429 2450
 /* APE registers.  Accessible through BAR1 */
2430 2451
 #define TG3_APE_EVENT			0x000c
@@ -2815,6 +2836,7 @@ struct tg3_link_config {
2815 2836
 #define DUPLEX_INVALID		0xff
2816 2837
 #define AUTONEG_INVALID		0xff
2817 2838
 	u16				active_speed;
2839
+	u32				rmt_adv;
2818 2840
 
2819 2841
 	/* When we go in and out of low power mode we need
2820 2842
 	 * to swap with this state.
@@ -3282,6 +3304,7 @@ struct tg3 {
3282 3304
 
3283 3305
 	u16				subsystem_vendor;
3284 3306
 	u16				subsystem_device;
3307
+	int				link_up;
3285 3308
 };
3286 3309
 
3287 3310
 #define TG3_TX_RING_SIZE		512
@@ -3410,6 +3433,39 @@ static inline u8 mii_resolve_flowctrl_fdx(u16 lcladv, u16 rmtadv)
3410 3433
 	return cap;
3411 3434
 }
3412 3435
 
3436
+static inline u32 mii_adv_to_ethtool_adv_x(u32 adv)
3437
+{
3438
+	u32 result = 0;
3439
+
3440
+	if (adv & ADVERTISE_1000XHALF)
3441
+		result |= ADVERTISED_1000baseT_Half;
3442
+	if (adv & ADVERTISE_1000XFULL)
3443
+		result |= ADVERTISED_1000baseT_Full;
3444
+	if (adv & ADVERTISE_1000XPAUSE)
3445
+		result |= ADVERTISED_Pause;
3446
+	if (adv & ADVERTISE_1000XPSE_ASYM)
3447
+		result |= ADVERTISED_Asym_Pause;
3448
+
3449
+	return result;
3450
+}
3451
+
3452
+static inline u32 ethtool_adv_to_mii_adv_x(u32 ethadv)
3453
+{
3454
+	u32 result = 0;
3455
+
3456
+	if (ethadv & ADVERTISED_1000baseT_Half)
3457
+		result |= ADVERTISE_1000XHALF;
3458
+	if (ethadv & ADVERTISED_1000baseT_Full)
3459
+		result |= ADVERTISE_1000XFULL;
3460
+	if (ethadv & ADVERTISED_Pause)
3461
+		result |= ADVERTISE_1000XPAUSE;
3462
+	if (ethadv & ADVERTISED_Asym_Pause)
3463
+		result |= ADVERTISE_1000XPSE_ASYM;
3464
+
3465
+	return result;
3466
+}
3467
+
3468
+
3413 3469
 #define ETH_FCS_LEN 4
3414 3470
 
3415 3471
 #endif /* !(_T3_H) */

+ 965
- 4
src/drivers/net/tg3/tg3_phy.c Näytä tiedosto

@@ -1287,6 +1287,970 @@ static void tg3_link_report(struct tg3 *tp)
1287 1287
 }
1288 1288
 #endif
1289 1289
 
1290
+struct tg3_fiber_aneginfo {
1291
+	int state;
1292
+#define ANEG_STATE_UNKNOWN		0
1293
+#define ANEG_STATE_AN_ENABLE		1
1294
+#define ANEG_STATE_RESTART_INIT		2
1295
+#define ANEG_STATE_RESTART		3
1296
+#define ANEG_STATE_DISABLE_LINK_OK	4
1297
+#define ANEG_STATE_ABILITY_DETECT_INIT	5
1298
+#define ANEG_STATE_ABILITY_DETECT	6
1299
+#define ANEG_STATE_ACK_DETECT_INIT	7
1300
+#define ANEG_STATE_ACK_DETECT		8
1301
+#define ANEG_STATE_COMPLETE_ACK_INIT	9
1302
+#define ANEG_STATE_COMPLETE_ACK		10
1303
+#define ANEG_STATE_IDLE_DETECT_INIT	11
1304
+#define ANEG_STATE_IDLE_DETECT		12
1305
+#define ANEG_STATE_LINK_OK		13
1306
+#define ANEG_STATE_NEXT_PAGE_WAIT_INIT	14
1307
+#define ANEG_STATE_NEXT_PAGE_WAIT	15
1308
+
1309
+	u32 flags;
1310
+#define MR_AN_ENABLE		0x00000001
1311
+#define MR_RESTART_AN		0x00000002
1312
+#define MR_AN_COMPLETE		0x00000004
1313
+#define MR_PAGE_RX		0x00000008
1314
+#define MR_NP_LOADED		0x00000010
1315
+#define MR_TOGGLE_TX		0x00000020
1316
+#define MR_LP_ADV_FULL_DUPLEX	0x00000040
1317
+#define MR_LP_ADV_HALF_DUPLEX	0x00000080
1318
+#define MR_LP_ADV_SYM_PAUSE	0x00000100
1319
+#define MR_LP_ADV_ASYM_PAUSE	0x00000200
1320
+#define MR_LP_ADV_REMOTE_FAULT1	0x00000400
1321
+#define MR_LP_ADV_REMOTE_FAULT2	0x00000800
1322
+#define MR_LP_ADV_NEXT_PAGE	0x00001000
1323
+#define MR_TOGGLE_RX		0x00002000
1324
+#define MR_NP_RX		0x00004000
1325
+
1326
+#define MR_LINK_OK		0x80000000
1327
+
1328
+	unsigned long link_time, cur_time;
1329
+
1330
+	u32 ability_match_cfg;
1331
+	int ability_match_count;
1332
+
1333
+	char ability_match, idle_match, ack_match;
1334
+
1335
+	u32 txconfig, rxconfig;
1336
+#define ANEG_CFG_NP		0x00000080
1337
+#define ANEG_CFG_ACK		0x00000040
1338
+#define ANEG_CFG_RF2		0x00000020
1339
+#define ANEG_CFG_RF1		0x00000010
1340
+#define ANEG_CFG_PS2		0x00000001
1341
+#define ANEG_CFG_PS1		0x00008000
1342
+#define ANEG_CFG_HD		0x00004000
1343
+#define ANEG_CFG_FD		0x00002000
1344
+#define ANEG_CFG_INVAL		0x00001f06
1345
+
1346
+};
1347
+#define ANEG_OK		0
1348
+#define ANEG_DONE	1
1349
+#define ANEG_TIMER_ENAB	2
1350
+#define ANEG_FAILED	-1
1351
+
1352
+#define ANEG_STATE_SETTLE_TIME	10000
1353
+
1354
+static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl)
1355
+{
1356
+	u16 miireg;
1357
+
1358
+	if ((flow_ctrl & FLOW_CTRL_TX) && (flow_ctrl & FLOW_CTRL_RX))
1359
+		miireg = ADVERTISE_1000XPAUSE;
1360
+	else if (flow_ctrl & FLOW_CTRL_TX)
1361
+		miireg = ADVERTISE_1000XPSE_ASYM;
1362
+	else if (flow_ctrl & FLOW_CTRL_RX)
1363
+		miireg = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM;
1364
+	else
1365
+		miireg = 0;
1366
+
1367
+	return miireg;
1368
+}
1369
+
1370
+static void tg3_init_bcm8002(struct tg3 *tp)
1371
+{
1372
+	u32 mac_status = tr32(MAC_STATUS);
1373
+	int i;
1374
+
1375
+	/* Reset when initting first time or we have a link. */
1376
+	if (tg3_flag(tp, INIT_COMPLETE) &&
1377
+	    !(mac_status & MAC_STATUS_PCS_SYNCED))
1378
+		return;
1379
+
1380
+	/* Set PLL lock range. */
1381
+	tg3_writephy(tp, 0x16, 0x8007);
1382
+
1383
+	/* SW reset */
1384
+	tg3_writephy(tp, MII_BMCR, BMCR_RESET);
1385
+
1386
+	/* Wait for reset to complete. */
1387
+	/* XXX schedule_timeout() ... */
1388
+	for (i = 0; i < 500; i++)
1389
+		udelay(10);
1390
+
1391
+	/* Config mode; select PMA/Ch 1 regs. */
1392
+	tg3_writephy(tp, 0x10, 0x8411);
1393
+
1394
+	/* Enable auto-lock and comdet, select txclk for tx. */
1395
+	tg3_writephy(tp, 0x11, 0x0a10);
1396
+
1397
+	tg3_writephy(tp, 0x18, 0x00a0);
1398
+	tg3_writephy(tp, 0x16, 0x41ff);
1399
+
1400
+	/* Assert and deassert POR. */
1401
+	tg3_writephy(tp, 0x13, 0x0400);
1402
+	udelay(40);
1403
+	tg3_writephy(tp, 0x13, 0x0000);
1404
+
1405
+	tg3_writephy(tp, 0x11, 0x0a50);
1406
+	udelay(40);
1407
+	tg3_writephy(tp, 0x11, 0x0a10);
1408
+
1409
+	/* Wait for signal to stabilize */
1410
+	/* XXX schedule_timeout() ... */
1411
+	for (i = 0; i < 15000; i++)
1412
+		udelay(10);
1413
+
1414
+	/* Deselect the channel register so we can read the PHYID
1415
+	 * later.
1416
+	 */
1417
+	tg3_writephy(tp, 0x10, 0x8011);
1418
+}
1419
+
1420
+static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
1421
+{
1422
+	u16 flowctrl;
1423
+	int current_link_up;
1424
+	u32 sg_dig_ctrl, sg_dig_status;
1425
+	u32 serdes_cfg, expected_sg_dig_ctrl;
1426
+	int workaround, port_a;
1427
+
1428
+	serdes_cfg = 0;
1429
+	expected_sg_dig_ctrl = 0;
1430
+	workaround = 0;
1431
+	port_a = 1;
1432
+	current_link_up = 0;
1433
+
1434
+	if (tp->pci_chip_rev_id != CHIPREV_ID_5704_A0 &&
1435
+	    tp->pci_chip_rev_id != CHIPREV_ID_5704_A1) {
1436
+		workaround = 1;
1437
+		if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
1438
+			port_a = 0;
1439
+
1440
+		/* preserve bits 0-11,13,14 for signal pre-emphasis */
1441
+		/* preserve bits 20-23 for voltage regulator */
1442
+		serdes_cfg = tr32(MAC_SERDES_CFG) & 0x00f06fff;
1443
+	}
1444
+
1445
+	sg_dig_ctrl = tr32(SG_DIG_CTRL);
1446
+
1447
+	if (tp->link_config.autoneg != AUTONEG_ENABLE) {
1448
+		if (sg_dig_ctrl & SG_DIG_USING_HW_AUTONEG) {
1449
+			if (workaround) {
1450
+				u32 val = serdes_cfg;
1451
+
1452
+				if (port_a)
1453
+					val |= 0xc010000;
1454
+				else
1455
+					val |= 0x4010000;
1456
+				tw32_f(MAC_SERDES_CFG, val);
1457
+			}
1458
+
1459
+			tw32_f(SG_DIG_CTRL, SG_DIG_COMMON_SETUP);
1460
+		}
1461
+		if (mac_status & MAC_STATUS_PCS_SYNCED) {
1462
+			tg3_setup_flow_control(tp, 0, 0);
1463
+			current_link_up = 1;
1464
+		}
1465
+		goto out;
1466
+	}
1467
+
1468
+	/* Want auto-negotiation.  */
1469
+	expected_sg_dig_ctrl = SG_DIG_USING_HW_AUTONEG | SG_DIG_COMMON_SETUP;
1470
+
1471
+	flowctrl = tg3_advert_flowctrl_1000X(tp->link_config.flowctrl);
1472
+	if (flowctrl & ADVERTISE_1000XPAUSE)
1473
+		expected_sg_dig_ctrl |= SG_DIG_PAUSE_CAP;
1474
+	if (flowctrl & ADVERTISE_1000XPSE_ASYM)
1475
+		expected_sg_dig_ctrl |= SG_DIG_ASYM_PAUSE;
1476
+
1477
+	if (sg_dig_ctrl != expected_sg_dig_ctrl) {
1478
+		if ((tp->phy_flags & TG3_PHYFLG_PARALLEL_DETECT) &&
1479
+		    tp->serdes_counter &&
1480
+		    ((mac_status & (MAC_STATUS_PCS_SYNCED |
1481
+				    MAC_STATUS_RCVD_CFG)) ==
1482
+		     MAC_STATUS_PCS_SYNCED)) {
1483
+			tp->serdes_counter--;
1484
+			current_link_up = 1;
1485
+			goto out;
1486
+		}
1487
+restart_autoneg:
1488
+		if (workaround)
1489
+			tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011000);
1490
+		tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | SG_DIG_SOFT_RESET);
1491
+		udelay(5);
1492
+		tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl);
1493
+
1494
+		tp->serdes_counter = SERDES_AN_TIMEOUT_5704S;
1495
+		tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
1496
+	} else if (mac_status & (MAC_STATUS_PCS_SYNCED |
1497
+				 MAC_STATUS_SIGNAL_DET)) {
1498
+		sg_dig_status = tr32(SG_DIG_STATUS);
1499
+		mac_status = tr32(MAC_STATUS);
1500
+
1501
+		if ((sg_dig_status & SG_DIG_AUTONEG_COMPLETE) &&
1502
+		    (mac_status & MAC_STATUS_PCS_SYNCED)) {
1503
+			u32 local_adv = 0, remote_adv = 0;
1504
+
1505
+			if (sg_dig_ctrl & SG_DIG_PAUSE_CAP)
1506
+				local_adv |= ADVERTISE_1000XPAUSE;
1507
+			if (sg_dig_ctrl & SG_DIG_ASYM_PAUSE)
1508
+				local_adv |= ADVERTISE_1000XPSE_ASYM;
1509
+
1510
+			if (sg_dig_status & SG_DIG_PARTNER_PAUSE_CAPABLE)
1511
+				remote_adv |= LPA_1000XPAUSE;
1512
+			if (sg_dig_status & SG_DIG_PARTNER_ASYM_PAUSE)
1513
+				remote_adv |= LPA_1000XPAUSE_ASYM;
1514
+
1515
+			tp->link_config.rmt_adv =
1516
+					   mii_adv_to_ethtool_adv_x(remote_adv);
1517
+
1518
+			tg3_setup_flow_control(tp, local_adv, remote_adv);
1519
+			current_link_up = 1;
1520
+			tp->serdes_counter = 0;
1521
+			tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
1522
+		} else if (!(sg_dig_status & SG_DIG_AUTONEG_COMPLETE)) {
1523
+			if (tp->serdes_counter)
1524
+				tp->serdes_counter--;
1525
+			else {
1526
+				if (workaround) {
1527
+					u32 val = serdes_cfg;
1528
+
1529
+					if (port_a)
1530
+						val |= 0xc010000;
1531
+					else
1532
+						val |= 0x4010000;
1533
+
1534
+					tw32_f(MAC_SERDES_CFG, val);
1535
+				}
1536
+
1537
+				tw32_f(SG_DIG_CTRL, SG_DIG_COMMON_SETUP);
1538
+				udelay(40);
1539
+
1540
+				/* Link parallel detection - link is up */
1541
+				/* only if we have PCS_SYNC and not */
1542
+				/* receiving config code words */
1543
+				mac_status = tr32(MAC_STATUS);
1544
+				if ((mac_status & MAC_STATUS_PCS_SYNCED) &&
1545
+				    !(mac_status & MAC_STATUS_RCVD_CFG)) {
1546
+					tg3_setup_flow_control(tp, 0, 0);
1547
+					current_link_up = 1;
1548
+					tp->phy_flags |=
1549
+						TG3_PHYFLG_PARALLEL_DETECT;
1550
+					tp->serdes_counter =
1551
+						SERDES_PARALLEL_DET_TIMEOUT;
1552
+				} else
1553
+					goto restart_autoneg;
1554
+			}
1555
+		}
1556
+	} else {
1557
+		tp->serdes_counter = SERDES_AN_TIMEOUT_5704S;
1558
+		tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
1559
+	}
1560
+
1561
+out:
1562
+	return current_link_up;
1563
+}
1564
+
1565
+static int tg3_fiber_aneg_smachine(struct tg3 *tp,
1566
+				   struct tg3_fiber_aneginfo *ap)
1567
+{
1568
+	u16 flowctrl;
1569
+	unsigned long delta;
1570
+	u32 rx_cfg_reg;
1571
+	int ret;
1572
+
1573
+	if (ap->state == ANEG_STATE_UNKNOWN) {
1574
+		ap->rxconfig = 0;
1575
+		ap->link_time = 0;
1576
+		ap->cur_time = 0;
1577
+		ap->ability_match_cfg = 0;
1578
+		ap->ability_match_count = 0;
1579
+		ap->ability_match = 0;
1580
+		ap->idle_match = 0;
1581
+		ap->ack_match = 0;
1582
+	}
1583
+	ap->cur_time++;
1584
+
1585
+	if (tr32(MAC_STATUS) & MAC_STATUS_RCVD_CFG) {
1586
+		rx_cfg_reg = tr32(MAC_RX_AUTO_NEG);
1587
+
1588
+		if (rx_cfg_reg != ap->ability_match_cfg) {
1589
+			ap->ability_match_cfg = rx_cfg_reg;
1590
+			ap->ability_match = 0;
1591
+			ap->ability_match_count = 0;
1592
+		} else {
1593
+			if (++ap->ability_match_count > 1) {
1594
+				ap->ability_match = 1;
1595
+				ap->ability_match_cfg = rx_cfg_reg;
1596
+			}
1597
+		}
1598
+		if (rx_cfg_reg & ANEG_CFG_ACK)
1599
+			ap->ack_match = 1;
1600
+		else
1601
+			ap->ack_match = 0;
1602
+
1603
+		ap->idle_match = 0;
1604
+	} else {
1605
+		ap->idle_match = 1;
1606
+		ap->ability_match_cfg = 0;
1607
+		ap->ability_match_count = 0;
1608
+		ap->ability_match = 0;
1609
+		ap->ack_match = 0;
1610
+
1611
+		rx_cfg_reg = 0;
1612
+	}
1613
+
1614
+	ap->rxconfig = rx_cfg_reg;
1615
+	ret = ANEG_OK;
1616
+
1617
+	switch (ap->state) {
1618
+	case ANEG_STATE_UNKNOWN:
1619
+		if (ap->flags & (MR_AN_ENABLE | MR_RESTART_AN))
1620
+			ap->state = ANEG_STATE_AN_ENABLE;
1621
+
1622
+		/* fallthru */
1623
+	case ANEG_STATE_AN_ENABLE:
1624
+		ap->flags &= ~(MR_AN_COMPLETE | MR_PAGE_RX);
1625
+		if (ap->flags & MR_AN_ENABLE) {
1626
+			ap->link_time = 0;
1627
+			ap->cur_time = 0;
1628
+			ap->ability_match_cfg = 0;
1629
+			ap->ability_match_count = 0;
1630
+			ap->ability_match = 0;
1631
+			ap->idle_match = 0;
1632
+			ap->ack_match = 0;
1633
+
1634
+			ap->state = ANEG_STATE_RESTART_INIT;
1635
+		} else {
1636
+			ap->state = ANEG_STATE_DISABLE_LINK_OK;
1637
+		}
1638
+		break;
1639
+
1640
+	case ANEG_STATE_RESTART_INIT:
1641
+		ap->link_time = ap->cur_time;
1642
+		ap->flags &= ~(MR_NP_LOADED);
1643
+		ap->txconfig = 0;
1644
+		tw32(MAC_TX_AUTO_NEG, 0);
1645
+		tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
1646
+		tw32_f(MAC_MODE, tp->mac_mode);
1647
+		udelay(40);
1648
+
1649
+		ret = ANEG_TIMER_ENAB;
1650
+		ap->state = ANEG_STATE_RESTART;
1651
+
1652
+		/* fallthru */
1653
+	case ANEG_STATE_RESTART:
1654
+		delta = ap->cur_time - ap->link_time;
1655
+		if (delta > ANEG_STATE_SETTLE_TIME)
1656
+			ap->state = ANEG_STATE_ABILITY_DETECT_INIT;
1657
+		else
1658
+			ret = ANEG_TIMER_ENAB;
1659
+		break;
1660
+
1661
+	case ANEG_STATE_DISABLE_LINK_OK:
1662
+		ret = ANEG_DONE;
1663
+		break;
1664
+
1665
+	case ANEG_STATE_ABILITY_DETECT_INIT:
1666
+		ap->flags &= ~(MR_TOGGLE_TX);
1667
+		ap->txconfig = ANEG_CFG_FD;
1668
+		flowctrl = tg3_advert_flowctrl_1000X(tp->link_config.flowctrl);
1669
+		if (flowctrl & ADVERTISE_1000XPAUSE)
1670
+			ap->txconfig |= ANEG_CFG_PS1;
1671
+		if (flowctrl & ADVERTISE_1000XPSE_ASYM)
1672
+			ap->txconfig |= ANEG_CFG_PS2;
1673
+		tw32(MAC_TX_AUTO_NEG, ap->txconfig);
1674
+		tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
1675
+		tw32_f(MAC_MODE, tp->mac_mode);
1676
+		udelay(40);
1677
+
1678
+		ap->state = ANEG_STATE_ABILITY_DETECT;
1679
+		break;
1680
+
1681
+	case ANEG_STATE_ABILITY_DETECT:
1682
+		if (ap->ability_match != 0 && ap->rxconfig != 0)
1683
+			ap->state = ANEG_STATE_ACK_DETECT_INIT;
1684
+		break;
1685
+
1686
+	case ANEG_STATE_ACK_DETECT_INIT:
1687
+		ap->txconfig |= ANEG_CFG_ACK;
1688
+		tw32(MAC_TX_AUTO_NEG, ap->txconfig);
1689
+		tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
1690
+		tw32_f(MAC_MODE, tp->mac_mode);
1691
+		udelay(40);
1692
+
1693
+		ap->state = ANEG_STATE_ACK_DETECT;
1694
+
1695
+		/* fallthru */
1696
+	case ANEG_STATE_ACK_DETECT:
1697
+		if (ap->ack_match != 0) {
1698
+			if ((ap->rxconfig & ~ANEG_CFG_ACK) ==
1699
+			    (ap->ability_match_cfg & ~ANEG_CFG_ACK)) {
1700
+				ap->state = ANEG_STATE_COMPLETE_ACK_INIT;
1701
+			} else {
1702
+				ap->state = ANEG_STATE_AN_ENABLE;
1703
+			}
1704
+		} else if (ap->ability_match != 0 &&
1705
+			   ap->rxconfig == 0) {
1706
+			ap->state = ANEG_STATE_AN_ENABLE;
1707
+		}
1708
+		break;
1709
+
1710
+	case ANEG_STATE_COMPLETE_ACK_INIT:
1711
+		if (ap->rxconfig & ANEG_CFG_INVAL) {
1712
+			ret = ANEG_FAILED;
1713
+			break;
1714
+		}
1715
+		ap->flags &= ~(MR_LP_ADV_FULL_DUPLEX |
1716
+			       MR_LP_ADV_HALF_DUPLEX |
1717
+			       MR_LP_ADV_SYM_PAUSE |
1718
+			       MR_LP_ADV_ASYM_PAUSE |
1719
+			       MR_LP_ADV_REMOTE_FAULT1 |
1720
+			       MR_LP_ADV_REMOTE_FAULT2 |
1721
+			       MR_LP_ADV_NEXT_PAGE |
1722
+			       MR_TOGGLE_RX |
1723
+			       MR_NP_RX);
1724
+		if (ap->rxconfig & ANEG_CFG_FD)
1725
+			ap->flags |= MR_LP_ADV_FULL_DUPLEX;
1726
+		if (ap->rxconfig & ANEG_CFG_HD)
1727
+			ap->flags |= MR_LP_ADV_HALF_DUPLEX;
1728
+		if (ap->rxconfig & ANEG_CFG_PS1)
1729
+			ap->flags |= MR_LP_ADV_SYM_PAUSE;
1730
+		if (ap->rxconfig & ANEG_CFG_PS2)
1731
+			ap->flags |= MR_LP_ADV_ASYM_PAUSE;
1732
+		if (ap->rxconfig & ANEG_CFG_RF1)
1733
+			ap->flags |= MR_LP_ADV_REMOTE_FAULT1;
1734
+		if (ap->rxconfig & ANEG_CFG_RF2)
1735
+			ap->flags |= MR_LP_ADV_REMOTE_FAULT2;
1736
+		if (ap->rxconfig & ANEG_CFG_NP)
1737
+			ap->flags |= MR_LP_ADV_NEXT_PAGE;
1738
+
1739
+		ap->link_time = ap->cur_time;
1740
+
1741
+		ap->flags ^= (MR_TOGGLE_TX);
1742
+		if (ap->rxconfig & 0x0008)
1743
+			ap->flags |= MR_TOGGLE_RX;
1744
+		if (ap->rxconfig & ANEG_CFG_NP)
1745
+			ap->flags |= MR_NP_RX;
1746
+		ap->flags |= MR_PAGE_RX;
1747
+
1748
+		ap->state = ANEG_STATE_COMPLETE_ACK;
1749
+		ret = ANEG_TIMER_ENAB;
1750
+		break;
1751
+
1752
+	case ANEG_STATE_COMPLETE_ACK:
1753
+		if (ap->ability_match != 0 &&
1754
+		    ap->rxconfig == 0) {
1755
+			ap->state = ANEG_STATE_AN_ENABLE;
1756
+			break;
1757
+		}
1758
+		delta = ap->cur_time - ap->link_time;
1759
+		if (delta > ANEG_STATE_SETTLE_TIME) {
1760
+			if (!(ap->flags & (MR_LP_ADV_NEXT_PAGE))) {
1761
+				ap->state = ANEG_STATE_IDLE_DETECT_INIT;
1762
+			} else {
1763
+				if ((ap->txconfig & ANEG_CFG_NP) == 0 &&
1764
+				    !(ap->flags & MR_NP_RX)) {
1765
+					ap->state = ANEG_STATE_IDLE_DETECT_INIT;
1766
+				} else {
1767
+					ret = ANEG_FAILED;
1768
+				}
1769
+			}
1770
+		}
1771
+		break;
1772
+
1773
+	case ANEG_STATE_IDLE_DETECT_INIT:
1774
+		ap->link_time = ap->cur_time;
1775
+		tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
1776
+		tw32_f(MAC_MODE, tp->mac_mode);
1777
+		udelay(40);
1778
+
1779
+		ap->state = ANEG_STATE_IDLE_DETECT;
1780
+		ret = ANEG_TIMER_ENAB;
1781
+		break;
1782
+
1783
+	case ANEG_STATE_IDLE_DETECT:
1784
+		if (ap->ability_match != 0 &&
1785
+		    ap->rxconfig == 0) {
1786
+			ap->state = ANEG_STATE_AN_ENABLE;
1787
+			break;
1788
+		}
1789
+		delta = ap->cur_time - ap->link_time;
1790
+		if (delta > ANEG_STATE_SETTLE_TIME) {
1791
+			/* XXX another gem from the Broadcom driver :( */
1792
+			ap->state = ANEG_STATE_LINK_OK;
1793
+		}
1794
+		break;
1795
+
1796
+	case ANEG_STATE_LINK_OK:
1797
+		ap->flags |= (MR_AN_COMPLETE | MR_LINK_OK);
1798
+		ret = ANEG_DONE;
1799
+		break;
1800
+
1801
+	case ANEG_STATE_NEXT_PAGE_WAIT_INIT:
1802
+		/* ??? unimplemented */
1803
+		break;
1804
+
1805
+	case ANEG_STATE_NEXT_PAGE_WAIT:
1806
+		/* ??? unimplemented */
1807
+		break;
1808
+
1809
+	default:
1810
+		ret = ANEG_FAILED;
1811
+		break;
1812
+	}
1813
+
1814
+	return ret;
1815
+}
1816
+
1817
+static int fiber_autoneg(struct tg3 *tp, u32 *txflags, u32 *rxflags)
1818
+{
1819
+	int res = 0;
1820
+	struct tg3_fiber_aneginfo aninfo;
1821
+	int status = ANEG_FAILED;
1822
+	unsigned int tick;
1823
+	u32 tmp;
1824
+
1825
+	tw32_f(MAC_TX_AUTO_NEG, 0);
1826
+
1827
+	tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
1828
+	tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
1829
+	udelay(40);
1830
+
1831
+	tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
1832
+	udelay(40);
1833
+
1834
+	memset(&aninfo, 0, sizeof(aninfo));
1835
+	aninfo.flags |= MR_AN_ENABLE;
1836
+	aninfo.state = ANEG_STATE_UNKNOWN;
1837
+	aninfo.cur_time = 0;
1838
+	tick = 0;
1839
+	while (++tick < 195000) {
1840
+		status = tg3_fiber_aneg_smachine(tp, &aninfo);
1841
+		if (status == ANEG_DONE || status == ANEG_FAILED)
1842
+			break;
1843
+
1844
+		udelay(1);
1845
+	}
1846
+
1847
+	tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
1848
+	tw32_f(MAC_MODE, tp->mac_mode);
1849
+	udelay(40);
1850
+
1851
+	*txflags = aninfo.txconfig;
1852
+	*rxflags = aninfo.flags;
1853
+
1854
+	if (status == ANEG_DONE &&
1855
+	    (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK |
1856
+			     MR_LP_ADV_FULL_DUPLEX)))
1857
+		res = 1;
1858
+
1859
+	return res;
1860
+}
1861
+
1862
+static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
1863
+{
1864
+	int current_link_up = 0;
1865
+
1866
+	if (!(mac_status & MAC_STATUS_PCS_SYNCED))
1867
+		goto out;
1868
+
1869
+	if (tp->link_config.autoneg == AUTONEG_ENABLE) {
1870
+		u32 txflags, rxflags;
1871
+		int i;
1872
+
1873
+		if (fiber_autoneg(tp, &txflags, &rxflags)) {
1874
+			u32 local_adv = 0, remote_adv = 0;
1875
+
1876
+			if (txflags & ANEG_CFG_PS1)
1877
+				local_adv |= ADVERTISE_1000XPAUSE;
1878
+			if (txflags & ANEG_CFG_PS2)
1879
+				local_adv |= ADVERTISE_1000XPSE_ASYM;
1880
+
1881
+			if (rxflags & MR_LP_ADV_SYM_PAUSE)
1882
+				remote_adv |= LPA_1000XPAUSE;
1883
+			if (rxflags & MR_LP_ADV_ASYM_PAUSE)
1884
+				remote_adv |= LPA_1000XPAUSE_ASYM;
1885
+
1886
+			tp->link_config.rmt_adv =
1887
+					   mii_adv_to_ethtool_adv_x(remote_adv);
1888
+
1889
+			tg3_setup_flow_control(tp, local_adv, remote_adv);
1890
+
1891
+			current_link_up = 1;
1892
+		}
1893
+		for (i = 0; i < 30; i++) {
1894
+			udelay(20);
1895
+			tw32_f(MAC_STATUS,
1896
+			       (MAC_STATUS_SYNC_CHANGED |
1897
+				MAC_STATUS_CFG_CHANGED));
1898
+			udelay(40);
1899
+			if ((tr32(MAC_STATUS) &
1900
+			     (MAC_STATUS_SYNC_CHANGED |
1901
+			      MAC_STATUS_CFG_CHANGED)) == 0)
1902
+				break;
1903
+		}
1904
+
1905
+		mac_status = tr32(MAC_STATUS);
1906
+		if (!current_link_up &&
1907
+		    (mac_status & MAC_STATUS_PCS_SYNCED) &&
1908
+		    !(mac_status & MAC_STATUS_RCVD_CFG))
1909
+			current_link_up = 1;
1910
+	} else {
1911
+		tg3_setup_flow_control(tp, 0, 0);
1912
+
1913
+		/* Forcing 1000FD link up. */
1914
+		current_link_up = 1;
1915
+
1916
+		tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS));
1917
+		udelay(40);
1918
+
1919
+		tw32_f(MAC_MODE, tp->mac_mode);
1920
+		udelay(40);
1921
+	}
1922
+
1923
+out:
1924
+	return current_link_up;
1925
+}
1926
+
1927
+static int tg3_test_and_report_link_chg(struct tg3 *tp, int curr_link_up)
1928
+{
1929
+	if (curr_link_up != tp->link_up) {
1930
+		if (curr_link_up) {
1931
+	                netdev_link_up(tp->dev);
1932
+		} else {
1933
+	                netdev_link_down(tp->dev);
1934
+			if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)
1935
+				tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
1936
+		}
1937
+
1938
+		tg3_link_report(tp);
1939
+		return 1;
1940
+	}
1941
+
1942
+	return 0;
1943
+}
1944
+
1945
+static void tg3_clear_mac_status(struct tg3 *tp)
1946
+{
1947
+	tw32(MAC_EVENT, 0);
1948
+
1949
+	tw32_f(MAC_STATUS,
1950
+	       MAC_STATUS_SYNC_CHANGED |
1951
+	       MAC_STATUS_CFG_CHANGED |
1952
+	       MAC_STATUS_MI_COMPLETION |
1953
+	       MAC_STATUS_LNKSTATE_CHANGED);
1954
+	udelay(40);
1955
+}
1956
+
1957
+static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
1958
+{
1959
+	u32 orig_pause_cfg;
1960
+	u16 orig_active_speed;
1961
+	u8 orig_active_duplex;
1962
+	u32 mac_status;
1963
+	int current_link_up = force_reset;
1964
+	int i;
1965
+
1966
+	orig_pause_cfg = tp->link_config.active_flowctrl;
1967
+	orig_active_speed = tp->link_config.active_speed;
1968
+	orig_active_duplex = tp->link_config.active_duplex;
1969
+
1970
+	if (!tg3_flag(tp, HW_AUTONEG) &&
1971
+	    tp->link_up &&
1972
+	    tg3_flag(tp, INIT_COMPLETE)) {
1973
+		mac_status = tr32(MAC_STATUS);
1974
+		mac_status &= (MAC_STATUS_PCS_SYNCED |
1975
+			       MAC_STATUS_SIGNAL_DET |
1976
+			       MAC_STATUS_CFG_CHANGED |
1977
+			       MAC_STATUS_RCVD_CFG);
1978
+		if (mac_status == (MAC_STATUS_PCS_SYNCED |
1979
+				   MAC_STATUS_SIGNAL_DET)) {
1980
+			tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED |
1981
+					    MAC_STATUS_CFG_CHANGED));
1982
+			return 0;
1983
+		}
1984
+	}
1985
+
1986
+	tw32_f(MAC_TX_AUTO_NEG, 0);
1987
+
1988
+	tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
1989
+	tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
1990
+	tw32_f(MAC_MODE, tp->mac_mode);
1991
+	udelay(40);
1992
+
1993
+	if (tp->phy_id == TG3_PHY_ID_BCM8002)
1994
+		tg3_init_bcm8002(tp);
1995
+
1996
+	/* Enable link change event even when serdes polling.  */
1997
+	tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
1998
+	udelay(40);
1999
+
2000
+	current_link_up = 0;
2001
+	tp->link_config.rmt_adv = 0;
2002
+	mac_status = tr32(MAC_STATUS);
2003
+
2004
+	if (tg3_flag(tp, HW_AUTONEG))
2005
+		current_link_up = tg3_setup_fiber_hw_autoneg(tp, mac_status);
2006
+	else
2007
+		current_link_up = tg3_setup_fiber_by_hand(tp, mac_status);
2008
+
2009
+	tp->hw_status->status =
2010
+		(SD_STATUS_UPDATED |
2011
+		 (tp->hw_status->status & ~SD_STATUS_LINK_CHG));
2012
+
2013
+	for (i = 0; i < 100; i++) {
2014
+		tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED |
2015
+				    MAC_STATUS_CFG_CHANGED));
2016
+		udelay(5);
2017
+		if ((tr32(MAC_STATUS) & (MAC_STATUS_SYNC_CHANGED |
2018
+					 MAC_STATUS_CFG_CHANGED |
2019
+					 MAC_STATUS_LNKSTATE_CHANGED)) == 0)
2020
+			break;
2021
+	}
2022
+
2023
+	mac_status = tr32(MAC_STATUS);
2024
+	if ((mac_status & MAC_STATUS_PCS_SYNCED) == 0) {
2025
+		current_link_up = 0;
2026
+		if (tp->link_config.autoneg == AUTONEG_ENABLE &&
2027
+		    tp->serdes_counter == 0) {
2028
+			tw32_f(MAC_MODE, (tp->mac_mode |
2029
+					  MAC_MODE_SEND_CONFIGS));
2030
+			udelay(1);
2031
+			tw32_f(MAC_MODE, tp->mac_mode);
2032
+		}
2033
+	}
2034
+
2035
+	if (current_link_up) {
2036
+		tp->link_config.active_speed = SPEED_1000;
2037
+		tp->link_config.active_duplex = DUPLEX_FULL;
2038
+		tw32(MAC_LED_CTRL, (tp->led_ctrl |
2039
+				    LED_CTRL_LNKLED_OVERRIDE |
2040
+				    LED_CTRL_1000MBPS_ON));
2041
+	} else {
2042
+		tp->link_config.active_speed = SPEED_UNKNOWN;
2043
+		tp->link_config.active_duplex = DUPLEX_UNKNOWN;
2044
+		tw32(MAC_LED_CTRL, (tp->led_ctrl |
2045
+				    LED_CTRL_LNKLED_OVERRIDE |
2046
+				    LED_CTRL_TRAFFIC_OVERRIDE));
2047
+	}
2048
+
2049
+	if (!tg3_test_and_report_link_chg(tp, current_link_up)) {
2050
+		u32 now_pause_cfg = tp->link_config.active_flowctrl;
2051
+		if (orig_pause_cfg != now_pause_cfg ||
2052
+		    orig_active_speed != tp->link_config.active_speed ||
2053
+		    orig_active_duplex != tp->link_config.active_duplex)
2054
+			tg3_link_report(tp);
2055
+	}
2056
+
2057
+	return 0;
2058
+}
2059
+
2060
+static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
2061
+{
2062
+	int err = 0;
2063
+	u32 bmsr, bmcr;
2064
+	u16 current_speed = SPEED_UNKNOWN;
2065
+	u8 current_duplex = DUPLEX_UNKNOWN;
2066
+	int current_link_up = 0;
2067
+	u32 local_adv, remote_adv, sgsr;
2068
+
2069
+	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
2070
+	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) &&
2071
+	     !tg3_readphy(tp, SERDES_TG3_1000X_STATUS, &sgsr) &&
2072
+	     (sgsr & SERDES_TG3_SGMII_MODE)) {
2073
+
2074
+		if (force_reset)
2075
+			tg3_phy_reset(tp);
2076
+
2077
+		tp->mac_mode &= ~MAC_MODE_PORT_MODE_MASK;
2078
+
2079
+		if (!(sgsr & SERDES_TG3_LINK_UP)) {
2080
+			tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
2081
+		} else {
2082
+			current_link_up = 1;
2083
+			if (sgsr & SERDES_TG3_SPEED_1000) {
2084
+				current_speed = SPEED_1000;
2085
+				tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
2086
+			} else if (sgsr & SERDES_TG3_SPEED_100) {
2087
+				current_speed = SPEED_100;
2088
+				tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
2089
+			} else {
2090
+				current_speed = SPEED_10;
2091
+				tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
2092
+			}
2093
+
2094
+			if (sgsr & SERDES_TG3_FULL_DUPLEX)
2095
+				current_duplex = DUPLEX_FULL;
2096
+			else
2097
+				current_duplex = DUPLEX_HALF;
2098
+		}
2099
+
2100
+		tw32_f(MAC_MODE, tp->mac_mode);
2101
+		udelay(40);
2102
+
2103
+		tg3_clear_mac_status(tp);
2104
+
2105
+		goto fiber_setup_done;
2106
+	}
2107
+
2108
+	tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
2109
+	tw32_f(MAC_MODE, tp->mac_mode);
2110
+	udelay(40);
2111
+
2112
+	tg3_clear_mac_status(tp);
2113
+
2114
+	if (force_reset)
2115
+		tg3_phy_reset(tp);
2116
+
2117
+	tp->link_config.rmt_adv = 0;
2118
+
2119
+	err |= tg3_readphy(tp, MII_BMSR, &bmsr);
2120
+	err |= tg3_readphy(tp, MII_BMSR, &bmsr);
2121
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
2122
+		if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP)
2123
+			bmsr |= BMSR_LSTATUS;
2124
+		else
2125
+			bmsr &= ~BMSR_LSTATUS;
2126
+	}
2127
+
2128
+	err |= tg3_readphy(tp, MII_BMCR, &bmcr);
2129
+
2130
+	if ((tp->link_config.autoneg == AUTONEG_ENABLE) && !force_reset &&
2131
+	    (tp->phy_flags & TG3_PHYFLG_PARALLEL_DETECT)) {
2132
+		/* do nothing, just check for link up at the end */
2133
+	} else if (tp->link_config.autoneg == AUTONEG_ENABLE) {
2134
+		u32 adv, newadv;
2135
+
2136
+		err |= tg3_readphy(tp, MII_ADVERTISE, &adv);
2137
+		newadv = adv & ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF |
2138
+				 ADVERTISE_1000XPAUSE |
2139
+				 ADVERTISE_1000XPSE_ASYM |
2140
+				 ADVERTISE_SLCT);
2141
+
2142
+		newadv |= tg3_advert_flowctrl_1000X(tp->link_config.flowctrl);
2143
+		newadv |= ethtool_adv_to_mii_adv_x(tp->link_config.advertising);
2144
+
2145
+		if ((newadv != adv) || !(bmcr & BMCR_ANENABLE)) {
2146
+			tg3_writephy(tp, MII_ADVERTISE, newadv);
2147
+			bmcr |= BMCR_ANENABLE | BMCR_ANRESTART;
2148
+			tg3_writephy(tp, MII_BMCR, bmcr);
2149
+
2150
+			tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
2151
+			tp->serdes_counter = SERDES_AN_TIMEOUT_5714S;
2152
+			tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
2153
+
2154
+			return err;
2155
+		}
2156
+	} else {
2157
+		u32 new_bmcr;
2158
+
2159
+		bmcr &= ~BMCR_SPEED1000;
2160
+		new_bmcr = bmcr & ~(BMCR_ANENABLE | BMCR_FULLDPLX);
2161
+
2162
+		if (tp->link_config.duplex == DUPLEX_FULL)
2163
+			new_bmcr |= BMCR_FULLDPLX;
2164
+
2165
+		if (new_bmcr != bmcr) {
2166
+			/* BMCR_SPEED1000 is a reserved bit that needs
2167
+			 * to be set on write.
2168
+			 */
2169
+			new_bmcr |= BMCR_SPEED1000;
2170
+
2171
+			/* Force a linkdown */
2172
+			if (tp->link_up) {
2173
+				u32 adv;
2174
+
2175
+				err |= tg3_readphy(tp, MII_ADVERTISE, &adv);
2176
+				adv &= ~(ADVERTISE_1000XFULL |
2177
+					 ADVERTISE_1000XHALF |
2178
+					 ADVERTISE_SLCT);
2179
+				tg3_writephy(tp, MII_ADVERTISE, adv);
2180
+				tg3_writephy(tp, MII_BMCR, bmcr |
2181
+							   BMCR_ANRESTART |
2182
+							   BMCR_ANENABLE);
2183
+				udelay(10);
2184
+	                        netdev_link_down(tp->dev);
2185
+			}
2186
+			tg3_writephy(tp, MII_BMCR, new_bmcr);
2187
+			bmcr = new_bmcr;
2188
+			err |= tg3_readphy(tp, MII_BMSR, &bmsr);
2189
+			err |= tg3_readphy(tp, MII_BMSR, &bmsr);
2190
+			if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
2191
+				if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP)
2192
+					bmsr |= BMSR_LSTATUS;
2193
+				else
2194
+					bmsr &= ~BMSR_LSTATUS;
2195
+			}
2196
+			tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
2197
+		}
2198
+	}
2199
+
2200
+	if (bmsr & BMSR_LSTATUS) {
2201
+		current_speed = SPEED_1000;
2202
+		current_link_up = 1;
2203
+		if (bmcr & BMCR_FULLDPLX)
2204
+			current_duplex = DUPLEX_FULL;
2205
+		else
2206
+			current_duplex = DUPLEX_HALF;
2207
+
2208
+		local_adv = 0;
2209
+		remote_adv = 0;
2210
+
2211
+		if (bmcr & BMCR_ANENABLE) {
2212
+			u32 common;
2213
+
2214
+			err |= tg3_readphy(tp, MII_ADVERTISE, &local_adv);
2215
+			err |= tg3_readphy(tp, MII_LPA, &remote_adv);
2216
+			common = local_adv & remote_adv;
2217
+			if (common & (ADVERTISE_1000XHALF |
2218
+				      ADVERTISE_1000XFULL)) {
2219
+				if (common & ADVERTISE_1000XFULL)
2220
+					current_duplex = DUPLEX_FULL;
2221
+				else
2222
+					current_duplex = DUPLEX_HALF;
2223
+
2224
+				tp->link_config.rmt_adv =
2225
+					   mii_adv_to_ethtool_adv_x(remote_adv);
2226
+			} else if (!tg3_flag(tp, 5780_CLASS)) {
2227
+				/* Link is up via parallel detect */
2228
+			} else {
2229
+				current_link_up = 0;
2230
+			}
2231
+		}
2232
+	}
2233
+
2234
+fiber_setup_done:
2235
+	if (current_link_up && current_duplex == DUPLEX_FULL)
2236
+		tg3_setup_flow_control(tp, local_adv, remote_adv);
2237
+
2238
+	tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX;
2239
+	if (tp->link_config.active_duplex == DUPLEX_HALF)
2240
+		tp->mac_mode |= MAC_MODE_HALF_DUPLEX;
2241
+
2242
+	tw32_f(MAC_MODE, tp->mac_mode);
2243
+	udelay(40);
2244
+
2245
+	tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
2246
+
2247
+	tp->link_config.active_speed = current_speed;
2248
+	tp->link_config.active_duplex = current_duplex;
2249
+
2250
+	tg3_test_and_report_link_chg(tp, current_link_up);
2251
+	return err;
2252
+}
2253
+
1290 2254
 static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
1291 2255
 {	DBGP("%s\n", __func__);
1292 2256
 
@@ -1559,15 +2523,12 @@ int tg3_setup_phy(struct tg3 *tp, int force_reset)
1559 2523
 	u32 val;
1560 2524
 	int err;
1561 2525
 
1562
-#if 0
1563 2526
 	if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES)
1564 2527
 		err = tg3_setup_fiber_phy(tp, force_reset);
1565 2528
 	else if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)
1566 2529
 		err = tg3_setup_fiber_mii_phy(tp, force_reset);
1567 2530
 	else
1568
-#endif
1569
-	/* FIXME: add only copper phy variants for now */
1570
-	err = tg3_setup_copper_phy(tp, force_reset);
2531
+		err = tg3_setup_copper_phy(tp, force_reset);
1571 2532
 
1572 2533
 	val = (2 << TX_LENGTHS_IPG_CRS_SHIFT) |
1573 2534
 	      (6 << TX_LENGTHS_IPG_SHIFT);

Loading…
Peruuta
Tallenna