summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/pci/if_rge.c48
1 files changed, 37 insertions, 11 deletions
diff --git a/sys/dev/pci/if_rge.c b/sys/dev/pci/if_rge.c
index 957dbd9fbb5..e89f7bf52ab 100644
--- a/sys/dev/pci/if_rge.c
+++ b/sys/dev/pci/if_rge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_rge.c,v 1.5 2020/07/22 00:48:02 kevlo Exp $ */
+/* $OpenBSD: if_rge.c,v 1.6 2020/08/07 13:53:58 kevlo Exp $ */
/*
* Copyright (c) 2019, 2020 Kevin Lo <kevlo@openbsd.org>
@@ -104,6 +104,7 @@ uint16_t rge_read_mac_ocp(struct rge_softc *, uint16_t);
void rge_write_ephy(struct rge_softc *, uint16_t, uint16_t);
uint16_t rge_read_ephy(struct rge_softc *, uint16_t);
void rge_write_phy(struct rge_softc *, uint16_t, uint16_t, uint16_t);
+uint16_t rge_read_phy(struct rge_softc *, uint16_t, uint16_t);
void rge_write_phy_ocp(struct rge_softc *, uint16_t, uint16_t);
uint16_t rge_read_phy_ocp(struct rge_softc *, uint16_t);
int rge_get_link_status(struct rge_softc *);
@@ -853,27 +854,34 @@ rge_ifmedia_upd(struct ifnet *ifp)
anar = gig = 0;
switch (IFM_SUBTYPE(ifm->ifm_media)) {
case IFM_AUTO:
- anar |= ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10;
- gig |= GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX;
+ anar = ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10;
+ gig = GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX;
val |= RGE_ADV_2500TFDX;
break;
case IFM_2500_T:
- anar |= ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10;
- gig |= GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX;
+ anar = ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10;
+ gig = GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX;
val |= RGE_ADV_2500TFDX;
ifp->if_baudrate = IF_Mbps(2500);
break;
case IFM_1000_T:
- anar |= ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10;
- gig |= GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX;
+ anar = ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10;
+ gig = GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX;
ifp->if_baudrate = IF_Gbps(1);
break;
case IFM_100_TX:
- anar |= ANAR_TX | ANAR_TX_FD;
+ gig = rge_read_phy(sc, 0, MII_100T2CR) &
+ ~(GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX);
+ anar = ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) ?
+ ANAR_TX | ANAR_TX_FD | ANAR_10_FD | ANAR_10 :
+ ANAR_TX | ANAR_10_FD | ANAR_10;
ifp->if_baudrate = IF_Mbps(100);
break;
case IFM_10_T:
- anar |= ANAR_10 | ANAR_10_FD;
+ gig = rge_read_phy(sc, 0, MII_100T2CR) &
+ ~(GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX);
+ anar = ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) ?
+ ANAR_10_FD | ANAR_10 : ANAR_10;
ifp->if_baudrate = IF_Mbps(10);
break;
default:
@@ -884,7 +892,8 @@ rge_ifmedia_upd(struct ifnet *ifp)
rge_write_phy(sc, 0, MII_ANAR, anar | ANAR_PAUSE_ASYM | ANAR_FC);
rge_write_phy(sc, 0, MII_100T2CR, gig);
rge_write_phy_ocp(sc, 0xa5d4, val);
- rge_write_phy(sc, 0, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
+ rge_write_phy(sc, 0, MII_BMCR, BMCR_RESET | BMCR_AUTOEN |
+ BMCR_STARTNEG);
return (0);
}
@@ -1469,6 +1478,9 @@ rge_phy_config(struct rge_softc *sc)
break; /* Can't happen. */
}
+ rge_write_phy(sc, 0x0a5b, 0x12,
+ rge_read_phy(sc, 0x0a5b, 0x12) & ~0x8000);
+
/* Disable EEE. */
RGE_MAC_CLRBIT(sc, 0xe040, 0x0003);
if (sc->rge_type == MAC_CFG2 || sc->rge_type == MAC_CFG3) {
@@ -2304,6 +2316,21 @@ rge_write_phy(struct rge_softc *sc, uint16_t addr, uint16_t reg, uint16_t val)
rge_write_phy_ocp(sc, phyaddr, val);
}
+uint16_t
+rge_read_phy(struct rge_softc *sc, uint16_t addr, uint16_t reg)
+{
+ uint16_t off, phyaddr;
+
+ phyaddr = addr ? addr : RGE_PHYBASE + (reg / 8);
+ phyaddr <<= 4;
+
+ off = addr ? reg : 0x10 + (reg % 8);
+
+ phyaddr += (off - 16) << 1;
+
+ return (rge_read_phy_ocp(sc, phyaddr));
+}
+
void
rge_write_phy_ocp(struct rge_softc *sc, uint16_t reg, uint16_t val)
{
@@ -2312,7 +2339,6 @@ rge_write_phy_ocp(struct rge_softc *sc, uint16_t reg, uint16_t val)
tmp = (reg >> 1) << RGE_PHYOCP_ADDR_SHIFT;
tmp |= RGE_PHYOCP_BUSY | val;
- //printf("%s: data32 = %x\n", sc->sc_dev.dv_xname, tmp);
RGE_WRITE_4(sc, RGE_PHYOCP, tmp);
for (i = 0; i < RGE_TIMEOUT; i++) {