Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev Add EEE(802.3az) support for I350, I210, I211, PCH2 ...
details: https://anonhg.NetBSD.org/src/rev/7316cdde41d5
branches: trunk
changeset: 447299:7316cdde41d5
user: msaitoh <msaitoh%NetBSD.org@localhost>
date: Mon Jan 07 01:43:22 2019 +0000
description:
Add EEE(802.3az) support for I350, I210, I211, PCH2 and newer.
Not yet for I354(C2000). It'll be supported after implementing MI MII clause
45 register read/write API.
diffstat:
sys/dev/mii/inbmphyreg.h | 15 ++-
sys/dev/pci/if_wm.c | 318 ++++++++++++++++++++++++++++++++++++++++------
2 files changed, 287 insertions(+), 46 deletions(-)
diffs (truncated from 553 to 300 lines):
diff -r dc29ce2c79f6 -r 7316cdde41d5 sys/dev/mii/inbmphyreg.h
--- a/sys/dev/mii/inbmphyreg.h Mon Jan 07 01:39:26 2019 +0000
+++ b/sys/dev/mii/inbmphyreg.h Mon Jan 07 01:43:22 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: inbmphyreg.h,v 1.15 2018/12/20 09:32:12 msaitoh Exp $ */
+/* $NetBSD: inbmphyreg.h,v 1.16 2019/01/07 01:43:22 msaitoh Exp $ */
/*******************************************************************************
Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
@@ -78,6 +78,19 @@
#define BME1000_PSCR_DOWNSHIFT_COUNTER_MASK 0x7000
#define BME1000_PSCR_DOWNSHIFT_COUNTER_SHIFT 12
+/* Extended Management Interface (EMI) Registers */
+#define I82579_EMI_ADDR 0x10
+#define I82579_EMI_DATA 0x11
+#define I82579_EEE_ADVERTISEMENT 0x040e /* IEEE MMD Register 7.60 */
+#define I82579_EEE_LP_ABILITY 0x040f /* IEEE MMD Register 7.61 */
+#define I82579_EEE_PCS_STATUS 0x182e
+#define I82579_LPI_PLL_SHUT 0x4412
+#define I82579_LPI_PLL_SHUT_100 __BIT(2) /* 100M LPI PLL Shut Enable */
+#define I217_EEE_PCS_STATUS 0x9401 /* IEEE MMD Register 3.1 */
+#define I217_EEE_CAPABILITY 0x8000 /* IEEE MMD Register 3.20 */
+#define I217_EEE_ADVERTISEMENT 0x8001 /* IEEE MMD Register 7.60 */
+#define I217_EEE_LP_ABILITY 0x8002 /* IEEE MMD Register 7.61 */
+
/* BM PHY Copper Specific Status */
#define BM_CS_STATUS BME1000_REG(0, 17)
#define BM_CS_STATUS_LINK_UP 0x0400
diff -r dc29ce2c79f6 -r 7316cdde41d5 sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c Mon Jan 07 01:39:26 2019 +0000
+++ b/sys/dev/pci/if_wm.c Mon Jan 07 01:43:22 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wm.c,v 1.613 2019/01/03 08:46:03 msaitoh Exp $ */
+/* $NetBSD: if_wm.c,v 1.614 2019/01/07 01:43:22 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.613 2019/01/03 08:46:03 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.614 2019/01/07 01:43:22 msaitoh Exp $");
#ifdef _KERNEL_OPT
#include "opt_net_mpsafe.h"
@@ -129,6 +129,7 @@
#include <machine/endian.h>
#include <dev/mii/mii.h>
+#include <dev/mii/mdio.h>
#include <dev/mii/miivar.h>
#include <dev/mii/miidevs.h>
#include <dev/mii/mii_bitbang.h>
@@ -514,7 +515,9 @@
int sc_funcid; /* unit number of the chip (0 to 3) */
int sc_flags; /* flags; see below */
int sc_if_flags; /* last if_flags */
+ int sc_ec_capenable; /* last ec_capenable */
int sc_flowflags; /* 802.3x flow control flags */
+ uint16_t eee_lp_ability; /* EEE link partner's ability */
int sc_align_tweak;
void *sc_ihs[WM_MAX_NINTR]; /*
@@ -852,10 +855,16 @@
static int wm_kmrn_readreg_locked(struct wm_softc *, int, uint16_t *);
static int wm_kmrn_writereg(struct wm_softc *, int, uint16_t);
static int wm_kmrn_writereg_locked(struct wm_softc *, int, uint16_t);
+/* EMI register related */
+static int wm_access_emi_reg_locked(device_t, int, uint16_t *, bool);
+static int wm_read_emi_reg_locked(device_t, int, uint16_t *);
+static int wm_write_emi_reg_locked(device_t, int, uint16_t);
/* SGMII */
static bool wm_sgmii_uses_mdio(struct wm_softc *);
static int wm_sgmii_readreg(device_t, int, int);
+static int wm_sgmii_readreg_locked(device_t, int, int, uint16_t *);
static void wm_sgmii_writereg(device_t, int, int, int);
+static int wm_sgmii_writereg_locked(device_t, int, int, uint16_t);
/* TBI related */
static bool wm_tbi_havesignal(struct wm_softc *, uint32_t);
static void wm_tbi_mediainit(struct wm_softc *);
@@ -967,7 +976,9 @@
/* LPLU (Low Power Link Up) */
static void wm_lplu_d0_disable(struct wm_softc *);
/* EEE */
-static void wm_set_eee_i350(struct wm_softc *);
+static int wm_set_eee_i350(struct wm_softc *);
+static int wm_set_eee_pchlan(struct wm_softc *);
+static int wm_set_eee(struct wm_softc *);
/*
* Workarounds (mainly PHY related).
@@ -2758,12 +2769,22 @@
sc->sc_mediatype = WM_MEDIATYPE_COPPER;
}
}
- snprintb(buf, sizeof(buf), WM_FLAGS, sc->sc_flags);
- aprint_verbose_dev(sc->sc_dev, "%s\n", buf);
+
+ if (sc->sc_type >= WM_T_PCH2)
+ sc->sc_flags |= WM_F_EEE;
+ else if ((sc->sc_type >= WM_T_I350) && (sc->sc_type <= WM_T_I211)
+ && (sc->sc_mediatype == WM_MEDIATYPE_COPPER)) {
+ /* XXX: Need special handling for I354. (not yet) */
+ if (sc->sc_type != WM_T_I354)
+ sc->sc_flags |= WM_F_EEE;
+ }
/* Set device properties (macflags) */
prop_dictionary_set_uint32(dict, "macflags", sc->sc_flags);
+ snprintb(buf, sizeof(buf), WM_FLAGS, sc->sc_flags);
+ aprint_verbose_dev(sc->sc_dev, "%s\n", buf);
+
/* Initialize the media structures accordingly. */
if (sc->sc_mediatype == WM_MEDIATYPE_COPPER)
wm_gmii_mediainit(sc, wmp->wmp_product);
@@ -2854,6 +2875,9 @@
sc->sc_ethercom.ec_capabilities |=
ETHERCAP_VLAN_MTU | ETHERCAP_VLAN_HWTAGGING;
+ if ((sc->sc_flags & WM_F_EEE) != 0)
+ sc->sc_ethercom.ec_capabilities |= ETHERCAP_EEE;
+
/*
* We can perform TCPv4 and UDPv4 checkums in-bound. Only
* on i82543 and later.
@@ -3256,6 +3280,8 @@
{
struct ifnet *ifp = &ec->ec_if;
struct wm_softc *sc = ifp->if_softc;
+ int iffchange, ecchange;
+ bool needreset = false;
int rc = 0;
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
@@ -3263,20 +3289,38 @@
WM_CORE_LOCK(sc);
- int change = ifp->if_flags ^ sc->sc_if_flags;
+ /*
+ * Check for if_flags.
+ * Main usage is to prevent linkdown when opening bpf.
+ */
+ iffchange = ifp->if_flags ^ sc->sc_if_flags;
sc->sc_if_flags = ifp->if_flags;
-
- if ((change & ~(IFF_CANTCHANGE | IFF_DEBUG)) != 0) {
- rc = ENETRESET;
- goto out;
- }
-
- if ((change & (IFF_PROMISC | IFF_ALLMULTI)) != 0)
+ if ((iffchange & ~(IFF_CANTCHANGE | IFF_DEBUG)) != 0) {
+ needreset = true;
+ goto ec;
+ }
+
+ /* iff related updates */
+ if ((iffchange & (IFF_PROMISC | IFF_ALLMULTI)) != 0)
wm_set_filter(sc);
wm_set_vlan(sc);
+ec:
+ /* Check for ec_capenable. */
+ ecchange = ec->ec_capenable ^ sc->sc_ec_capenable;
+ sc->sc_ec_capenable = ec->ec_capenable;
+ if ((ecchange & ~ETHERCAP_EEE) != 0) {
+ needreset = true;
+ goto out;
+ }
+
+ /* ec related updates */
+ wm_set_eee(sc);
+
out:
+ if (needreset)
+ rc = ENETRESET;
WM_CORE_UNLOCK(sc);
return rc;
@@ -4992,13 +5036,7 @@
/* reload sc_ctrl */
sc->sc_ctrl = CSR_READ(sc, WMREG_CTRL);
- if (sc->sc_type == WM_T_I354) {
-#if 0
- /* I354 uses an external PHY */
- wm_set_eee_i354(sc);
-#endif
- } else if ((sc->sc_type >= WM_T_I350) && (sc->sc_type <= WM_T_I211))
- wm_set_eee_i350(sc);
+ wm_set_eee(sc);
/*
* For PCH, this write will make sure that any noise will be detected
@@ -5624,6 +5662,7 @@
wm_init_locked(struct ifnet *ifp)
{
struct wm_softc *sc = ifp->if_softc;
+ struct ethercom *ec = &sc->sc_ethercom;
int i, j, trynum, error = 0;
uint32_t reg;
@@ -6098,7 +6137,7 @@
|| (sc->sc_type == WM_T_I210))
sc->sc_rctl |= RCTL_SECRC;
- if (((sc->sc_ethercom.ec_capabilities & ETHERCAP_JUMBO_MTU) != 0)
+ if (((ec->ec_capabilities & ETHERCAP_JUMBO_MTU) != 0)
&& (ifp->if_mtu > ETHERMTU)) {
sc->sc_rctl |= RCTL_LPE;
if ((sc->sc_flags & WM_F_NEWQUEUE) != 0)
@@ -6181,7 +6220,9 @@
ifp->if_flags &= ~IFF_OACTIVE;
out:
+ /* Save last flags for the callback */
sc->sc_if_flags = ifp->if_flags;
+ sc->sc_ec_capenable = ec->ec_capenable;
if (error)
log(LOG_ERR, "%s: interface not running\n",
device_xname(sc->sc_dev));
@@ -9002,6 +9043,9 @@
((sc->sc_mii.mii_media_status & IFM_ACTIVE) != 0));
}
+ /* Clear link partner's EEE ability */
+ sc->eee_lp_ability = 0;
+
/* FEXTNVM6 K1-off workaround */
if (sc->sc_type == WM_T_PCH_SPT) {
reg = CSR_READ(sc, WMREG_FEXTNVM6);
@@ -9027,6 +9071,11 @@
default:
break;
}
+
+ /* Enable/Disable EEE after link up */
+ if (sc->sc_phytype > WMPHY_82579)
+ wm_set_eee_pchlan(sc);
+
} else if (icr & ICR_RXSEQ) {
DPRINTF(WM_DEBUG_LINK, ("%s: LINK Receive sequence error\n",
device_xname(sc->sc_dev)));
@@ -9932,6 +9981,9 @@
if (new_readreg == wm_gmii_hv_readreg) {
sc->phy.readreg_locked = wm_gmii_hv_readreg_locked;
sc->phy.writereg_locked = wm_gmii_hv_writereg_locked;
+ } else if (new_readreg == wm_sgmii_readreg) {
+ sc->phy.readreg_locked = wm_sgmii_readreg_locked;
+ sc->phy.writereg_locked = wm_sgmii_writereg_locked;
} else if (new_readreg == wm_gmii_i82544_readreg) {
sc->phy.readreg_locked = wm_gmii_i82544_readreg_locked;
sc->phy.writereg_locked = wm_gmii_i82544_writereg_locked;
@@ -11286,6 +11338,41 @@
return 0;
}
+/*
+ * EMI register related (82579, WMPHY_I217(PCH2 and newer))
+ * This access method is different from IEEE MMD.
+ */
+static int
+wm_access_emi_reg_locked(device_t dev, int reg, uint16_t *val, bool rd)
+{
+ struct wm_softc *sc = device_private(dev);
+ int rv;
+
+ rv = sc->phy.writereg_locked(dev, 2, I82579_EMI_ADDR, reg);
+ if (rv != 0)
+ return rv;
+
+ if (rd)
+ rv = sc->phy.readreg_locked(dev, 2, I82579_EMI_DATA, val);
+ else
+ rv = sc->phy.writereg_locked(dev, 2, I82579_EMI_DATA, *val);
+ return rv;
+}
+
+static int
+wm_read_emi_reg_locked(device_t dev, int reg, uint16_t *val)
+{
+
+ return wm_access_emi_reg_locked(dev, reg, val, true);
+}
+
+static int
+wm_write_emi_reg_locked(device_t dev, int reg, uint16_t val)
+{
+
+ return wm_access_emi_reg_locked(dev, reg, &val, false);
+}
+
/* SGMII related */
/*
Home |
Main Index |
Thread Index |
Old Index