Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci - Add wm_oem_bits_config_ich8lan() to control LP...



details:   https://anonhg.NetBSD.org/src/rev/9ad3ee86134d
branches:  trunk
changeset: 446010:9ad3ee86134d
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Tue Nov 20 04:04:42 2018 +0000

description:
- Add wm_oem_bits_config_ich8lan() to control LPLU and GbE setting base on
  the NVM's info.
- Modify wm_enable_wakeup() to reduce difference against FreeBSD and Linux.
  This modification affects to ICH8 and newer devices. I217 Rapid Start
  Technology support have not written yet (it's TODO).

diffstat:

 sys/dev/pci/if_wm.c |  191 ++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 156 insertions(+), 35 deletions(-)

diffs (261 lines):

diff -r 220b538796e8 -r 9ad3ee86134d sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Tue Nov 20 03:52:03 2018 +0000
+++ b/sys/dev/pci/if_wm.c       Tue Nov 20 04:04:42 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.599 2018/11/20 03:52:03 msaitoh Exp $      */
+/*     $NetBSD: if_wm.c,v 1.600 2018/11/20 04:04:42 msaitoh Exp $      */
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -83,7 +83,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.599 2018/11/20 03:52:03 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.600 2018/11/20 04:04:42 msaitoh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -720,6 +720,7 @@
 static void    wm_phy_post_reset(struct wm_softc *);
 static int     wm_write_smbus_addr(struct wm_softc *);
 static void    wm_init_lcd_from_nvm(struct wm_softc *);
+static int     wm_oem_bits_config_ich8lan(struct wm_softc *, bool);
 static void    wm_initialize_hardware_bits(struct wm_softc *);
 static uint32_t        wm_rxpbs_adjust_82580(uint32_t);
 static void    wm_reset_phy(struct wm_softc *);
@@ -955,6 +956,7 @@
 static int     wm_ulp_disable(struct wm_softc *);
 static void    wm_enable_phy_wakeup(struct wm_softc *);
 static void    wm_igp3_phy_powerdown_workaround_ich8lan(struct wm_softc *);
+static void    wm_suspend_workarounds_ich8lan(struct wm_softc *);
 static void    wm_enable_wakeup(struct wm_softc *);
 static void    wm_disable_aspm(struct wm_softc *);
 /* LPLU (Low Power Link Up) */
@@ -3878,7 +3880,8 @@
        /* Configure the LCD with the extended configuration region in NVM */
        wm_init_lcd_from_nvm(sc);
 
-       /* XXX Configure the LCD with the OEM bits in NVM */
+       /* Configure the LCD with the OEM bits in NVM */
+       wm_oem_bits_config_ich8lan(sc, true);
 
        if (sc->sc_type == WM_T_PCH2) {
                /* Ungate automatic PHY configuration on non-managed 82579 */
@@ -4031,6 +4034,72 @@
        return;
 }
     
+/*
+ *  wm_oem_bits_config_ich8lan - SW-based LCD Configuration
+ *  @sc:       pointer to the HW structure
+ *  @d0_state: boolean if entering d0 or d3 device state
+ *
+ *  SW will configure Gbe Disable and LPLU based on the NVM. The four bits are
+ *  collectively called OEM bits.  The OEM Write Enable bit and SW Config bit
+ *  in NVM determines whether HW should configure LPLU and Gbe Disable.
+ */
+int
+wm_oem_bits_config_ich8lan(struct wm_softc *sc, bool d0_state)
+{
+       uint32_t mac_reg;
+       uint16_t oem_reg;
+       int rv;
+
+       if (sc->sc_type < WM_T_PCH)
+               return 0;
+
+       rv = sc->phy.acquire(sc);
+       if (rv != 0)
+               return rv;
+
+       if (sc->sc_type == WM_T_PCH) {
+               mac_reg = CSR_READ(sc, WMREG_EXTCNFCTR);
+               if ((mac_reg & EXTCNFCTR_OEM_WRITE_ENABLE) != 0)
+                       goto release;
+       }
+
+       mac_reg = CSR_READ(sc, WMREG_FEXTNVM);
+       if ((mac_reg & FEXTNVM_SW_CONFIG_ICH8M) == 0)
+               goto release;
+
+       mac_reg = CSR_READ(sc, WMREG_PHY_CTRL);
+       
+       rv = wm_gmii_hv_readreg_locked(sc->sc_dev, 1, HV_OEM_BITS, &oem_reg);
+       if (rv != 0)
+               goto release;
+       oem_reg &= ~(HV_OEM_BITS_A1KDIS | HV_OEM_BITS_LPLU);
+
+       if (d0_state) {
+               if ((mac_reg & PHY_CTRL_GBE_DIS) != 0)
+                       oem_reg |= HV_OEM_BITS_A1KDIS;
+               if ((mac_reg & PHY_CTRL_D0A_LPLU) != 0)
+                       oem_reg |= HV_OEM_BITS_LPLU;
+       } else {
+               if ((mac_reg & (PHY_CTRL_GBE_DIS | PHY_CTRL_NOND0A_GBE_DIS))
+                   != 0)
+                       oem_reg |= HV_OEM_BITS_A1KDIS;
+               if ((mac_reg & (PHY_CTRL_D0A_LPLU | PHY_CTRL_NOND0A_LPLU))
+                   != 0)
+                       oem_reg |= HV_OEM_BITS_LPLU;
+       }
+
+       /* Set Restart auto-neg to activate the bits */
+       if ((d0_state || (sc->sc_type != WM_T_PCH))
+           && (wm_phy_resetisblocked(sc) == false))
+               oem_reg |= HV_OEM_BITS_ANEGNOW;
+
+       rv = wm_gmii_hv_writereg_locked(sc->sc_dev, 1, HV_OEM_BITS, oem_reg);
+
+release:
+       sc->phy.release(sc);
+
+       return rv;
+}
 
 /* Init hardware bits */
 void
@@ -14121,6 +14190,85 @@
        }
 }
 
+/*
+ *  e1000_suspend_workarounds_ich8lan - workarounds needed during S0->Sx
+ *  @sc: pointer to the HW structure
+ *
+ *  During S0 to Sx transition, it is possible the link remains at gig
+ *  instead of negotiating to a lower speed.  Before going to Sx, set
+ *  'Gig Disable' to force link speed negotiation to a lower speed based on
+ *  the LPLU setting in the NVM or custom setting.  For PCH and newer parts,
+ *  the OEM bits PHY register (LED, GbE disable and LPLU configurations) also
+ *  needs to be written.
+ *  Parts that support (and are linked to a partner which support) EEE in
+ *  100Mbps should disable LPLU since 100Mbps w/ EEE requires less power
+ *  than 10Mbps w/o EEE.
+ */
+static void
+wm_suspend_workarounds_ich8lan(struct wm_softc *sc)
+{
+       uint32_t phy_ctrl;
+
+       phy_ctrl = CSR_READ(sc, WMREG_PHY_CTRL);
+       phy_ctrl |= PHY_CTRL_GBE_DIS;
+
+       if (sc->sc_phytype == WMPHY_I217) {
+               uint16_t devid = sc->sc_pcidevid;
+
+               if ((devid == PCI_PRODUCT_INTEL_I218_LM) ||
+                   (devid == PCI_PRODUCT_INTEL_I218_V) ||
+                   (devid == PCI_PRODUCT_INTEL_I218_LM3) ||
+                   (devid == PCI_PRODUCT_INTEL_I218_V3) ||
+                   (sc->sc_type >= WM_T_PCH_SPT))
+                       CSR_WRITE(sc, WMREG_FEXTNVM6,
+                           CSR_READ(sc, WMREG_FEXTNVM6)
+                           & ~FEXTNVM6_REQ_PLL_CLK);
+
+#if 0 /* notyet */
+               if (sc->phy.acquire(sc) != 0)
+                       goto out;
+
+               /* XXX Do workaround for EEE */
+
+               /*
+                * For i217 Intel Rapid Start Technology support,
+                * when the system is going into Sx and no manageability engine
+                * is present, the driver must configure proxy to reset only on
+                * power good.  LPI (Low Power Idle) state must also reset only
+                * on power good, as well as the MTA (Multicast table array).
+                * The SMBus release must also be disabled on LCD reset.
+                */
+
+               /*
+                * Enable MTA to reset for Intel Rapid Start Technology
+                * Support
+                */
+
+               sc->phy.release(sc);
+#endif
+       }
+#if 0
+out:
+#endif
+       CSR_WRITE(sc, WMREG_PHY_CTRL, phy_ctrl);
+
+       if (sc->sc_type == WM_T_ICH8)
+               wm_gig_downshift_workaround_ich8lan(sc);
+
+       if (sc->sc_type >= WM_T_PCH) {
+               wm_oem_bits_config_ich8lan(sc, false);
+
+               /* Reset PHY to activate OEM bits on 82577/8 */
+               if (sc->sc_type == WM_T_PCH)
+                       wm_reset_phy(sc);
+               
+               if (sc->phy.acquire(sc) != 0)
+                       return;
+               wm_write_smbus_addr(sc);
+               sc->phy.release(sc);
+       }
+}
+
 static void
 wm_enable_wakeup(struct wm_softc *sc)
 {
@@ -14139,38 +14287,6 @@
            | CTRL_SWDPIN(3));
        CSR_WRITE(sc, WMREG_WUC, WUC_APME);
 
-       /* ICH workaround */
-       switch (sc->sc_type) {
-       case WM_T_ICH8:
-       case WM_T_ICH9:
-       case WM_T_ICH10:
-       case WM_T_PCH:
-       case WM_T_PCH2:
-       case WM_T_PCH_LPT:
-       case WM_T_PCH_SPT:
-       case WM_T_PCH_CNP:
-               /* Disable gig during WOL */
-               reg = CSR_READ(sc, WMREG_PHY_CTRL);
-               reg |= PHY_CTRL_D0A_LPLU | PHY_CTRL_GBE_DIS;
-               CSR_WRITE(sc, WMREG_PHY_CTRL, reg);
-               if (sc->sc_type == WM_T_PCH)
-                       wm_gmii_reset(sc);
-
-               /* Power down workaround */
-               if (sc->sc_phytype == WMPHY_82577) {
-                       struct mii_softc *child;
-
-                       /* Assume that the PHY is copper */
-                       child = LIST_FIRST(&sc->sc_mii.mii_phys);
-                       if ((child != NULL) && (child->mii_mpd_rev <= 2))
-                               sc->sc_mii.mii_writereg(sc->sc_dev, 1,
-                                   (768 << 5) | 25, 0x0444); /* magic num */
-               }
-               break;
-       default:
-               break;
-       }
-
        /* Keep the laser running on fiber adapters */
        if ((sc->sc_mediatype == WM_MEDIATYPE_FIBER)
            || (sc->sc_mediatype == WM_MEDIATYPE_SERDES)) {
@@ -14179,6 +14295,10 @@
                CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
        }
 
+       if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9) ||
+           (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH))
+               wm_suspend_workarounds_ich8lan(sc);
+
        reg = CSR_READ(sc, WMREG_WUFC) | WUFC_MAG;
 #if 0  /* for the multicast packet */
        reg |= WUFC_MC;
@@ -14188,6 +14308,7 @@
        if (sc->sc_type >= WM_T_PCH)
                wm_enable_phy_wakeup(sc);
        else {
+               /* Enable wakeup by the MAC */
                CSR_WRITE(sc, WMREG_WUC, CSR_READ(sc, WMREG_WUC) | WUC_PME_EN);
                CSR_WRITE(sc, WMREG_WUFC, reg);
        }



Home | Main Index | Thread Index | Old Index