Fixes the rx stall problem on 82578 by MANY workaround code.
We need more work for 82577.
This commit is contained in:
parent
79f027bbd6
commit
86ff2cac75
|
@ -0,0 +1,110 @@
|
||||||
|
/* $NetBSD: inbmphyreg.h,v 1.1 2010/01/14 18:56:01 msaitoh Exp $ */
|
||||||
|
/*******************************************************************************
|
||||||
|
Copyright (c) 2001-2005, Intel Corporation
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the Intel Corporation nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copied from the Intel code, and then modified to match NetBSD
|
||||||
|
* style for MII registers more.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DEV_MII_INBMPHYREG_H_
|
||||||
|
#define _DEV_MII_INBMPHYREG_H_
|
||||||
|
|
||||||
|
/* Bits...
|
||||||
|
* 15-5: page
|
||||||
|
* 4-0: register offset
|
||||||
|
*/
|
||||||
|
#define BME1000_PAGE_SHIFT 5
|
||||||
|
#define BME1000_REG(page, reg) \
|
||||||
|
(((page) << BME1000_PAGE_SHIFT) | ((reg) & BME1000_MAX_REG_ADDRESS))
|
||||||
|
|
||||||
|
#define BME1000_MAX_REG_ADDRESS 0x1f /* 5 bit address bus (0-0x1f) */
|
||||||
|
#define BME1000_MAX_MULTI_PAGE_REG 0xf /* Registers equal on all pages */
|
||||||
|
|
||||||
|
#define BM_PHY_REG_PAGE(offset) \
|
||||||
|
((uint16_t)(((offset) >> BME1000_PAGE_SHIFT) & 0xffff))
|
||||||
|
#define BM_PHY_REG_NUM(offset) \
|
||||||
|
((uint16_t)((offset) & BME1000_MAX_REG_ADDRESS) \
|
||||||
|
| (((offset) >> (21 - BME1000_PAGE_SHIFT)) & ~BME1000_MAX_REG_ADDRESS))
|
||||||
|
|
||||||
|
/* BME1000 Specific Registers */
|
||||||
|
#define BME1000_PHY_SPEC_CTRL BME1000_REG(0, 16) /* PHY Specific Control */
|
||||||
|
#define BME1000_PSCR_DISABLE_JABBER 0x0001 /* 1=Disable Jabber */
|
||||||
|
#define BME1000_PSCR_POLARITY_REVERSAL_DISABLE 0x0002 /* 1=Polarity Reversal Disabled */
|
||||||
|
#define BME1000_PSCR_POWER_DOWN 0x0004 /* 1=Power Down */
|
||||||
|
#define BME1000_PSCR_COPPER_TRANSMITER_DISABLE 0x0008 /* 1=Transmitter Disabled */
|
||||||
|
#define BME1000_PSCR_CROSSOVER_MODE_MASK 0x0060
|
||||||
|
#define BME1000_PSCR_CROSSOVER_MODE_MDI 0x0000 /* 00=Manual MDI configuration */
|
||||||
|
#define BME1000_PSCR_CROSSOVER_MODE_MDIX 0x0020 /* 01=Manual MDIX configuration */
|
||||||
|
#define BME1000_PSCR_CROSSOVER_MODE_AUTO 0x0060 /* 11=Automatic crossover */
|
||||||
|
#define BME1000_PSCR_ENALBE_EXTENDED_DISTANCE 0x0080 /* 1=Enable Extended Distance */
|
||||||
|
#define BME1000_PSCR_ENERGY_DETECT_MASK 0x0300
|
||||||
|
#define BME1000_PSCR_ENERGY_DETECT_OFF 0x0000 /* 00,01=Off */
|
||||||
|
#define BME1000_PSCR_ENERGY_DETECT_RX 0x0200 /* 10=Sense on Rx only (Energy Detect) */
|
||||||
|
#define BME1000_PSCR_ENERGY_DETECT_RX_TM 0x0300 /* 11=Sense and Tx NLP */
|
||||||
|
#define BME1000_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force Link Good */
|
||||||
|
#define BME1000_PSCR_DOWNSHIFT_ENABLE 0x0800 /* 1=Enable Downshift */
|
||||||
|
#define BME1000_PSCR_DOWNSHIFT_COUNTER_MASK 0x7000
|
||||||
|
#define BME1000_PSCR_DOWNSHIFT_COUNTER_SHIFT 12
|
||||||
|
|
||||||
|
#define BME1000_PHY_PAGE_SELECT BME1000_REG(0, 22) /* Page Select */
|
||||||
|
|
||||||
|
#define BME1000_BIAS_SETTING 29
|
||||||
|
#define BME1000_BIAS_SETTING2 30
|
||||||
|
|
||||||
|
#define I82578_ADDR_REG 29
|
||||||
|
#define I82577_ADDR_REG 16
|
||||||
|
#define I82577_CFG_REG 22
|
||||||
|
|
||||||
|
#define HV_OEM_BITS BME1000_REG(0, 25)
|
||||||
|
#define HV_OEM_BITS_LPLU (1 << 2)
|
||||||
|
#define HV_OEM_BITS_A1KDIS (1 << 6)
|
||||||
|
#define HV_OEM_BITS_ANEGNOW (1 << 10)
|
||||||
|
|
||||||
|
#define HV_INTC_FC_PAGE_START 768
|
||||||
|
#define BM_PORT_CTRL_PAGE 769
|
||||||
|
|
||||||
|
#define IGP3_KMRN_DIAG BME1000_REG(770, 19)
|
||||||
|
|
||||||
|
#define HV_MUX_DATA_CTRL BME1000_REG(776, 16)
|
||||||
|
#define HV_MUX_DATA_CTRL_FORCE_SPEED (1 << 2)
|
||||||
|
#define HV_MUX_DATA_CTRL_GEN_TO_MAC (1 << 10)
|
||||||
|
|
||||||
|
#define BM_WUC_PAGE 800
|
||||||
|
#define BM_WUC BME1000_REG(BM_WUC_PAGE, 1)
|
||||||
|
#define BM_WUC_ADDRESS_OPCODE 0x11
|
||||||
|
#define BM_WUC_DATA_OPCODE 0x12
|
||||||
|
#define BM_WUC_ENABLE_PAGE BM_PORT_CTRL_PAGE
|
||||||
|
#define BM_WUC_ENABLE_REG 17
|
||||||
|
#define BM_WUC_ENABLE_BIT (1 << 2)
|
||||||
|
#define BM_WUC_HOST_WU_BIT (1 << 4)
|
||||||
|
|
||||||
|
#endif /* _DEV_MII_INBMPHYREG_H_ */
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: if_wm.c,v 1.191 2010/01/12 22:26:30 msaitoh Exp $ */
|
/* $NetBSD: if_wm.c,v 1.192 2010/01/14 18:56:02 msaitoh Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
|
* Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
|
||||||
|
@ -76,7 +76,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.191 2010/01/12 22:26:30 msaitoh Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.192 2010/01/14 18:56:02 msaitoh Exp $");
|
||||||
|
|
||||||
#include "bpfilter.h"
|
#include "bpfilter.h"
|
||||||
#include "rnd.h"
|
#include "rnd.h"
|
||||||
|
@ -124,6 +124,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.191 2010/01/12 22:26:30 msaitoh Exp $");
|
||||||
#include <dev/mii/mii_bitbang.h>
|
#include <dev/mii/mii_bitbang.h>
|
||||||
#include <dev/mii/ikphyreg.h>
|
#include <dev/mii/ikphyreg.h>
|
||||||
#include <dev/mii/igphyreg.h>
|
#include <dev/mii/igphyreg.h>
|
||||||
|
#include <dev/mii/inbmphyreg.h>
|
||||||
|
|
||||||
#include <dev/pci/pcireg.h>
|
#include <dev/pci/pcireg.h>
|
||||||
#include <dev/pci/pcivar.h>
|
#include <dev/pci/pcivar.h>
|
||||||
|
@ -249,7 +250,9 @@ struct wm_softc {
|
||||||
pci_chipset_tag_t sc_pc;
|
pci_chipset_tag_t sc_pc;
|
||||||
pcitag_t sc_pcitag;
|
pcitag_t sc_pcitag;
|
||||||
|
|
||||||
wm_chip_type sc_type; /* chip type */
|
wm_chip_type sc_type; /* MAC type */
|
||||||
|
int sc_rev; /* MAC revision */
|
||||||
|
wm_phy_type sc_phytype; /* PHY type */
|
||||||
int sc_flags; /* flags; see below */
|
int sc_flags; /* flags; see below */
|
||||||
int sc_if_flags; /* last if_flags */
|
int sc_if_flags; /* last if_flags */
|
||||||
int sc_bus_speed; /* PCI/PCIX bus speed */
|
int sc_bus_speed; /* PCI/PCIX bus speed */
|
||||||
|
@ -366,6 +369,7 @@ struct wm_softc {
|
||||||
#endif
|
#endif
|
||||||
int sc_ich8_flash_base;
|
int sc_ich8_flash_base;
|
||||||
int sc_ich8_flash_bank_size;
|
int sc_ich8_flash_bank_size;
|
||||||
|
int sc_nvm_k1_enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define WM_RXCHAIN_RESET(sc) \
|
#define WM_RXCHAIN_RESET(sc) \
|
||||||
|
@ -520,8 +524,8 @@ static int wm_gmii_i80003_readreg(device_t, int, int);
|
||||||
static void wm_gmii_i80003_writereg(device_t, int, int, int);
|
static void wm_gmii_i80003_writereg(device_t, int, int, int);
|
||||||
static int wm_gmii_bm_readreg(device_t, int, int);
|
static int wm_gmii_bm_readreg(device_t, int, int);
|
||||||
static void wm_gmii_bm_writereg(device_t, int, int, int);
|
static void wm_gmii_bm_writereg(device_t, int, int, int);
|
||||||
static int wm_gmii_kv_readreg(device_t, int, int);
|
static int wm_gmii_hv_readreg(device_t, int, int);
|
||||||
static void wm_gmii_kv_writereg(device_t, int, int, int);
|
static void wm_gmii_hv_writereg(device_t, int, int, int);
|
||||||
|
|
||||||
static void wm_gmii_statchg(device_t);
|
static void wm_gmii_statchg(device_t);
|
||||||
|
|
||||||
|
@ -562,6 +566,9 @@ static int wm_check_mng_mode_generic(struct wm_softc *);
|
||||||
static int wm_check_reset_block(struct wm_softc *);
|
static int wm_check_reset_block(struct wm_softc *);
|
||||||
static void wm_get_hw_control(struct wm_softc *);
|
static void wm_get_hw_control(struct wm_softc *);
|
||||||
static int wm_check_for_link(struct wm_softc *);
|
static int wm_check_for_link(struct wm_softc *);
|
||||||
|
static void wm_hv_phy_workaround_ich8lan(struct wm_softc *);
|
||||||
|
static void wm_k1_gig_workaround_hv(struct wm_softc *, int);
|
||||||
|
static void wm_configure_k1_ich8lan(struct wm_softc *, int);
|
||||||
|
|
||||||
CFATTACH_DECL_NEW(wm, sizeof(struct wm_softc),
|
CFATTACH_DECL_NEW(wm, sizeof(struct wm_softc),
|
||||||
wm_match, wm_attach, NULL, NULL);
|
wm_match, wm_attach, NULL, NULL);
|
||||||
|
@ -991,18 +998,18 @@ wm_attach(device_t parent, device_t self, void *aux)
|
||||||
else
|
else
|
||||||
sc->sc_dmat = pa->pa_dmat;
|
sc->sc_dmat = pa->pa_dmat;
|
||||||
|
|
||||||
preg = PCI_REVISION(pci_conf_read(pc, pa->pa_tag, PCI_CLASS_REG));
|
sc->sc_rev = PCI_REVISION(pci_conf_read(pc, pa->pa_tag, PCI_CLASS_REG));
|
||||||
aprint_naive(": Ethernet controller\n");
|
aprint_naive(": Ethernet controller\n");
|
||||||
aprint_normal(": %s, rev. %d\n", wmp->wmp_name, preg);
|
aprint_normal(": %s, rev. %d\n", wmp->wmp_name, sc->sc_rev);
|
||||||
|
|
||||||
sc->sc_type = wmp->wmp_type;
|
sc->sc_type = wmp->wmp_type;
|
||||||
if (sc->sc_type < WM_T_82543) {
|
if (sc->sc_type < WM_T_82543) {
|
||||||
if (preg < 2) {
|
if (sc->sc_rev < 2) {
|
||||||
aprint_error_dev(sc->sc_dev,
|
aprint_error_dev(sc->sc_dev,
|
||||||
"i82542 must be at least rev. 2\n");
|
"i82542 must be at least rev. 2\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (preg < 3)
|
if (sc->sc_rev < 3)
|
||||||
sc->sc_type = WM_T_82542_2_0;
|
sc->sc_type = WM_T_82542_2_0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1575,6 +1582,18 @@ wm_attach(device_t parent, device_t self, void *aux)
|
||||||
sc->sc_tdt_reg = WMREG_TDT;
|
sc->sc_tdt_reg = WMREG_TDT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sc->sc_type == WM_T_PCH) {
|
||||||
|
uint16_t val;
|
||||||
|
|
||||||
|
/* Save the NVM K1 bit setting */
|
||||||
|
wm_read_eeprom(sc, EEPROM_OFF_K1_CONFIG, 1, &val);
|
||||||
|
|
||||||
|
if ((val & EEPROM_K1_CONFIG_ENABLE) != 0)
|
||||||
|
sc->sc_nvm_k1_enabled = 1;
|
||||||
|
else
|
||||||
|
sc->sc_nvm_k1_enabled = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine if we're TBI or GMII mode, and initialize the
|
* Determine if we're TBI or GMII mode, and initialize the
|
||||||
* media structures accordingly.
|
* media structures accordingly.
|
||||||
|
@ -2896,74 +2915,101 @@ wm_rxintr(struct wm_softc *sc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* wm_linkintr:
|
* wm_linkintr_gmii:
|
||||||
*
|
*
|
||||||
* Helper; handle link interrupts.
|
* Helper; handle link interrupts for GMII.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
wm_linkintr(struct wm_softc *sc, uint32_t icr)
|
wm_linkintr_gmii(struct wm_softc *sc, uint32_t icr)
|
||||||
|
{
|
||||||
|
|
||||||
|
DPRINTF(WM_DEBUG_LINK, ("%s: %s:\n", device_xname(sc->sc_dev),
|
||||||
|
__func__));
|
||||||
|
|
||||||
|
if (icr & ICR_LSC) {
|
||||||
|
DPRINTF(WM_DEBUG_LINK,
|
||||||
|
("%s: LINK: LSC -> mii_tick\n",
|
||||||
|
device_xname(sc->sc_dev)));
|
||||||
|
mii_tick(&sc->sc_mii);
|
||||||
|
if (sc->sc_type == WM_T_82543) {
|
||||||
|
int miistatus, active;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* With 82543, we need to force speed and
|
||||||
|
* duplex on the MAC equal to what the PHY
|
||||||
|
* speed and duplex configuration is.
|
||||||
|
*/
|
||||||
|
miistatus = sc->sc_mii.mii_media_status;
|
||||||
|
|
||||||
|
if (miistatus & IFM_ACTIVE) {
|
||||||
|
active = sc->sc_mii.mii_media_active;
|
||||||
|
sc->sc_ctrl &= ~(CTRL_SPEED_MASK | CTRL_FD);
|
||||||
|
switch (IFM_SUBTYPE(active)) {
|
||||||
|
case IFM_10_T:
|
||||||
|
sc->sc_ctrl |= CTRL_SPEED_10;
|
||||||
|
break;
|
||||||
|
case IFM_100_TX:
|
||||||
|
sc->sc_ctrl |= CTRL_SPEED_100;
|
||||||
|
break;
|
||||||
|
case IFM_1000_T:
|
||||||
|
sc->sc_ctrl |= CTRL_SPEED_1000;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
* fiber?
|
||||||
|
* Shoud not enter here.
|
||||||
|
*/
|
||||||
|
printf("unknown media (%x)\n",
|
||||||
|
active);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (active & IFM_FDX)
|
||||||
|
sc->sc_ctrl |= CTRL_FD;
|
||||||
|
CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
|
||||||
|
}
|
||||||
|
} else if (sc->sc_type == WM_T_PCH) {
|
||||||
|
wm_k1_gig_workaround_hv(sc,
|
||||||
|
((sc->sc_mii.mii_media_status & IFM_ACTIVE) != 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sc->sc_phytype == WMPHY_82578)
|
||||||
|
&& (IFM_SUBTYPE(sc->sc_mii.mii_media_active)
|
||||||
|
== IFM_1000_T)) {
|
||||||
|
|
||||||
|
if ((sc->sc_mii.mii_media_status & IFM_ACTIVE) != 0) {
|
||||||
|
printf("XXX link sall wa\n");
|
||||||
|
delay(200*1000); /* XXX too big */
|
||||||
|
|
||||||
|
/* Link stall fix for link up */
|
||||||
|
wm_gmii_hv_writereg(sc->sc_dev, 1,
|
||||||
|
HV_MUX_DATA_CTRL,
|
||||||
|
HV_MUX_DATA_CTRL_GEN_TO_MAC
|
||||||
|
| HV_MUX_DATA_CTRL_FORCE_SPEED);
|
||||||
|
wm_gmii_hv_writereg(sc->sc_dev, 1,
|
||||||
|
HV_MUX_DATA_CTRL,
|
||||||
|
HV_MUX_DATA_CTRL_GEN_TO_MAC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (icr & ICR_RXSEQ) {
|
||||||
|
DPRINTF(WM_DEBUG_LINK,
|
||||||
|
("%s: LINK Receive sequence error\n",
|
||||||
|
device_xname(sc->sc_dev)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* wm_linkintr_tbi:
|
||||||
|
*
|
||||||
|
* Helper; handle link interrupts for TBI mode.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
wm_linkintr_tbi(struct wm_softc *sc, uint32_t icr)
|
||||||
{
|
{
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
|
|
||||||
DPRINTF(WM_DEBUG_LINK, ("%s: %s:\n", device_xname(sc->sc_dev),
|
DPRINTF(WM_DEBUG_LINK, ("%s: %s:\n", device_xname(sc->sc_dev),
|
||||||
__func__));
|
__func__));
|
||||||
/*
|
|
||||||
* If we get a link status interrupt on a 1000BASE-T
|
|
||||||
* device, just fall into the normal MII tick path.
|
|
||||||
*/
|
|
||||||
if (sc->sc_flags & WM_F_HAS_MII) {
|
|
||||||
if (icr & ICR_LSC) {
|
|
||||||
DPRINTF(WM_DEBUG_LINK,
|
|
||||||
("%s: LINK: LSC -> mii_tick\n",
|
|
||||||
device_xname(sc->sc_dev)));
|
|
||||||
mii_tick(&sc->sc_mii);
|
|
||||||
if (sc->sc_type == WM_T_82543) {
|
|
||||||
int miistatus, active;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* With 82543, we need to force speed and
|
|
||||||
* duplex on the MAC equal to what the PHY
|
|
||||||
* speed and duplex configuration is.
|
|
||||||
*/
|
|
||||||
miistatus = sc->sc_mii.mii_media_status;
|
|
||||||
|
|
||||||
if (miistatus & IFM_ACTIVE) {
|
|
||||||
active = sc->sc_mii.mii_media_active;
|
|
||||||
sc->sc_ctrl &= ~(CTRL_SPEED_MASK
|
|
||||||
| CTRL_FD);
|
|
||||||
switch (IFM_SUBTYPE(active)) {
|
|
||||||
case IFM_10_T:
|
|
||||||
sc->sc_ctrl |= CTRL_SPEED_10;
|
|
||||||
break;
|
|
||||||
case IFM_100_TX:
|
|
||||||
sc->sc_ctrl |= CTRL_SPEED_100;
|
|
||||||
break;
|
|
||||||
case IFM_1000_T:
|
|
||||||
sc->sc_ctrl |= CTRL_SPEED_1000;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/*
|
|
||||||
* fiber?
|
|
||||||
* Shoud not enter here.
|
|
||||||
*/
|
|
||||||
printf("unknown media (%x)\n",
|
|
||||||
active);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (active & IFM_FDX)
|
|
||||||
sc->sc_ctrl |= CTRL_FD;
|
|
||||||
CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (icr & ICR_RXSEQ) {
|
|
||||||
DPRINTF(WM_DEBUG_LINK,
|
|
||||||
("%s: LINK Receive sequence error\n",
|
|
||||||
device_xname(sc->sc_dev)));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TBI mode */
|
|
||||||
status = CSR_READ(sc, WMREG_STATUS);
|
status = CSR_READ(sc, WMREG_STATUS);
|
||||||
if (icr & ICR_LSC) {
|
if (icr & ICR_LSC) {
|
||||||
if (status & STATUS_LU) {
|
if (status & STATUS_LU) {
|
||||||
|
@ -3009,6 +3055,21 @@ wm_linkintr(struct wm_softc *sc, uint32_t icr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* wm_linkintr:
|
||||||
|
*
|
||||||
|
* Helper; handle link interrupts.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
wm_linkintr(struct wm_softc *sc, uint32_t icr)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (sc->sc_flags & WM_F_HAS_MII)
|
||||||
|
wm_linkintr_gmii(sc, icr);
|
||||||
|
else
|
||||||
|
wm_linkintr_tbi(sc, icr);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* wm_tick:
|
* wm_tick:
|
||||||
*
|
*
|
||||||
|
@ -3159,10 +3220,6 @@ wm_reset(struct wm_softc *sc)
|
||||||
delay(5000);
|
delay(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sc->sc_type == WM_T_PCH) {
|
|
||||||
/* Save K1 */
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (sc->sc_type) {
|
switch (sc->sc_type) {
|
||||||
case WM_T_82544: /* XXX check whether WM_F_IOH_VALID is set */
|
case WM_T_82544: /* XXX check whether WM_F_IOH_VALID is set */
|
||||||
case WM_T_82541:
|
case WM_T_82541:
|
||||||
|
@ -3303,6 +3360,9 @@ wm_reset(struct wm_softc *sc)
|
||||||
/* reload sc_ctrl */
|
/* reload sc_ctrl */
|
||||||
sc->sc_ctrl = CSR_READ(sc, WMREG_CTRL);
|
sc->sc_ctrl = CSR_READ(sc, WMREG_CTRL);
|
||||||
|
|
||||||
|
/* dummy read from WUC */
|
||||||
|
if (sc->sc_type == WM_T_PCH)
|
||||||
|
reg = wm_gmii_hv_readreg(sc->sc_dev, 1, BM_WUC);
|
||||||
/*
|
/*
|
||||||
* For PCH, this write will make sure that any noise will be detected
|
* For PCH, this write will make sure that any noise will be detected
|
||||||
* as a CRC error and be dropped rather than show up as a bad packet
|
* as a CRC error and be dropped rather than show up as a bad packet
|
||||||
|
@ -3390,6 +3450,11 @@ wm_init(struct ifnet *ifp)
|
||||||
if (sc->sc_flags & WM_F_HAS_MII)
|
if (sc->sc_flags & WM_F_HAS_MII)
|
||||||
wm_gmii_reset(sc);
|
wm_gmii_reset(sc);
|
||||||
|
|
||||||
|
reg = CSR_READ(sc, WMREG_CTRL_EXT);
|
||||||
|
/* Enable PHY low-power state when MAC is at D3 w/o WoL */
|
||||||
|
if (sc->sc_type == WM_T_PCH)
|
||||||
|
CSR_WRITE(sc, WMREG_CTRL_EXT, reg | CTRL_EXT_PHYPDEN);
|
||||||
|
|
||||||
/* Initialize the transmit descriptor ring. */
|
/* Initialize the transmit descriptor ring. */
|
||||||
memset(sc->sc_txdescs, 0, WM_TXDESCSIZE(sc));
|
memset(sc->sc_txdescs, 0, WM_TXDESCSIZE(sc));
|
||||||
WM_CDTXSYNC(sc, 0, WM_NTXDESC(sc),
|
WM_CDTXSYNC(sc, 0, WM_NTXDESC(sc),
|
||||||
|
@ -4779,7 +4844,7 @@ wm_gmii_reset(struct wm_softc *sc)
|
||||||
case WM_T_82573:
|
case WM_T_82573:
|
||||||
case WM_T_82574:
|
case WM_T_82574:
|
||||||
case WM_T_82583:
|
case WM_T_82583:
|
||||||
/* XXX sould get sw semaphore, too */
|
/* XXX should get sw semaphore, too */
|
||||||
rv = wm_get_swsm_semaphore(sc);
|
rv = wm_get_swsm_semaphore(sc);
|
||||||
break;
|
break;
|
||||||
case WM_T_80003:
|
case WM_T_80003:
|
||||||
|
@ -4874,11 +4939,6 @@ wm_gmii_reset(struct wm_softc *sc)
|
||||||
delay(100);
|
delay(100);
|
||||||
CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
|
CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
|
||||||
delay(150);
|
delay(150);
|
||||||
|
|
||||||
/* Allow time for h/w to get to a quiescent state afer reset */
|
|
||||||
delay(10*1000);
|
|
||||||
|
|
||||||
/* XXX add code to set LED after phy reset */
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("%s: %s: unknown type\n", device_xname(sc->sc_dev),
|
panic("%s: %s: unknown type\n", device_xname(sc->sc_dev),
|
||||||
|
@ -4943,36 +5003,34 @@ wm_gmii_reset(struct wm_softc *sc)
|
||||||
case WM_T_ICH9:
|
case WM_T_ICH9:
|
||||||
case WM_T_ICH10:
|
case WM_T_ICH10:
|
||||||
case WM_T_PCH:
|
case WM_T_PCH:
|
||||||
|
/* Allow time for h/w to get to a quiescent state afer reset */
|
||||||
delay(10*1000);
|
delay(10*1000);
|
||||||
|
|
||||||
if (sc->sc_type == WM_T_PCH) {
|
if (sc->sc_type == WM_T_PCH) {
|
||||||
/* XXX hv_phy_workaround */
|
wm_hv_phy_workaround_ich8lan(sc);
|
||||||
|
|
||||||
/* dummy read from WUC */
|
|
||||||
}
|
|
||||||
/* XXX SW LCD configuration from NVM */
|
|
||||||
|
|
||||||
if (sc->sc_type == WM_T_PCH) {
|
|
||||||
/* XXX Configure the LCD with the OEM bits in NVM */
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
/*
|
/*
|
||||||
* We shlould make the new driver for 8257[78] and
|
* dummy read to clear the phy wakeup bit after lcd
|
||||||
* move these code into it.
|
* reset
|
||||||
*/
|
*/
|
||||||
#define HV_OEM_BITS ((0 << 5) | 25)
|
reg = wm_gmii_hv_readreg(sc->sc_dev, 1, BM_WUC);
|
||||||
#define HV_OEM_BITS_LPLU (1 << 2)
|
}
|
||||||
#define HV_OEM_BITS_A1KDIS (1 << 6)
|
|
||||||
#define HV_OEM_BITS_ANEGNOW (1 << 10)
|
/*
|
||||||
#endif
|
* XXX Configure the LCD with th extended configuration region
|
||||||
|
* in NVM
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Configure the LCD with the OEM bits in NVM */
|
||||||
|
if (sc->sc_type == WM_T_PCH) {
|
||||||
/*
|
/*
|
||||||
* Disable LPLU.
|
* Disable LPLU.
|
||||||
* XXX It seems that 82567 has LPLU, too.
|
* XXX It seems that 82567 has LPLU, too.
|
||||||
*/
|
*/
|
||||||
reg = wm_gmii_kv_readreg(sc->sc_dev, 1, HV_OEM_BITS);
|
reg = wm_gmii_hv_readreg(sc->sc_dev, 1, HV_OEM_BITS);
|
||||||
reg &= ~(HV_OEM_BITS_A1KDIS| HV_OEM_BITS_LPLU);
|
reg &= ~(HV_OEM_BITS_A1KDIS| HV_OEM_BITS_LPLU);
|
||||||
reg |= HV_OEM_BITS_ANEGNOW;
|
reg |= HV_OEM_BITS_ANEGNOW;
|
||||||
wm_gmii_kv_writereg(sc->sc_dev, 1, HV_OEM_BITS, reg);
|
wm_gmii_hv_writereg(sc->sc_dev, 1, HV_OEM_BITS, reg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -5014,11 +5072,17 @@ wm_gmii_mediainit(struct wm_softc *sc, pci_product_id_t prodid)
|
||||||
switch (prodid) {
|
switch (prodid) {
|
||||||
case PCI_PRODUCT_INTEL_PCH_M_LM:
|
case PCI_PRODUCT_INTEL_PCH_M_LM:
|
||||||
case PCI_PRODUCT_INTEL_PCH_M_LC:
|
case PCI_PRODUCT_INTEL_PCH_M_LC:
|
||||||
|
/* 82577 */
|
||||||
|
sc->sc_phytype = WMPHY_82577;
|
||||||
|
sc->sc_mii.mii_readreg = wm_gmii_hv_readreg;
|
||||||
|
sc->sc_mii.mii_writereg = wm_gmii_hv_writereg;
|
||||||
|
break;
|
||||||
case PCI_PRODUCT_INTEL_PCH_D_DM:
|
case PCI_PRODUCT_INTEL_PCH_D_DM:
|
||||||
case PCI_PRODUCT_INTEL_PCH_D_DC:
|
case PCI_PRODUCT_INTEL_PCH_D_DC:
|
||||||
/* 82577 or 82578 */
|
/* 82578 */
|
||||||
sc->sc_mii.mii_readreg = wm_gmii_kv_readreg;
|
sc->sc_phytype = WMPHY_82578;
|
||||||
sc->sc_mii.mii_writereg = wm_gmii_kv_writereg;
|
sc->sc_mii.mii_readreg = wm_gmii_hv_readreg;
|
||||||
|
sc->sc_mii.mii_writereg = wm_gmii_hv_writereg;
|
||||||
break;
|
break;
|
||||||
case PCI_PRODUCT_INTEL_82801I_BM:
|
case PCI_PRODUCT_INTEL_82801I_BM:
|
||||||
case PCI_PRODUCT_INTEL_82801J_R_BM_LM:
|
case PCI_PRODUCT_INTEL_82801J_R_BM_LM:
|
||||||
|
@ -5027,6 +5091,7 @@ wm_gmii_mediainit(struct wm_softc *sc, pci_product_id_t prodid)
|
||||||
case PCI_PRODUCT_INTEL_82801J_D_BM_LF:
|
case PCI_PRODUCT_INTEL_82801J_D_BM_LF:
|
||||||
case PCI_PRODUCT_INTEL_82801J_R_BM_V:
|
case PCI_PRODUCT_INTEL_82801J_R_BM_V:
|
||||||
/* 82567 */
|
/* 82567 */
|
||||||
|
sc->sc_phytype = WMPHY_BM;
|
||||||
sc->sc_mii.mii_readreg = wm_gmii_bm_readreg;
|
sc->sc_mii.mii_readreg = wm_gmii_bm_readreg;
|
||||||
sc->sc_mii.mii_writereg = wm_gmii_bm_writereg;
|
sc->sc_mii.mii_writereg = wm_gmii_bm_writereg;
|
||||||
break;
|
break;
|
||||||
|
@ -5066,8 +5131,10 @@ wm_gmii_mediainit(struct wm_softc *sc, pci_product_id_t prodid)
|
||||||
if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
|
if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
|
||||||
ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
|
ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
|
||||||
ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
|
ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
|
||||||
} else
|
sc->sc_phytype = WMPHY_NONE;
|
||||||
|
} else {
|
||||||
ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
|
ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -5405,7 +5472,7 @@ wm_gmii_bm_readreg(device_t self, int phy, int reg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg > GG82563_MAX_REG_ADDRESS) {
|
if (reg > BME1000_MAX_MULTI_PAGE_REG) {
|
||||||
if (phy == 1)
|
if (phy == 1)
|
||||||
wm_gmii_i82544_writereg(self, phy, 0x1f,
|
wm_gmii_i82544_writereg(self, phy, 0x1f,
|
||||||
reg);
|
reg);
|
||||||
|
@ -5439,7 +5506,7 @@ wm_gmii_bm_writereg(device_t self, int phy, int reg, int val)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg > GG82563_MAX_REG_ADDRESS) {
|
if (reg > BME1000_MAX_MULTI_PAGE_REG) {
|
||||||
if (phy == 1)
|
if (phy == 1)
|
||||||
wm_gmii_i82544_writereg(self, phy, 0x1f,
|
wm_gmii_i82544_writereg(self, phy, 0x1f,
|
||||||
reg);
|
reg);
|
||||||
|
@ -5453,17 +5520,61 @@ wm_gmii_bm_writereg(device_t self, int phy, int reg, int val)
|
||||||
wm_put_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM);
|
wm_put_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wm_access_phy_wakeup_reg_bm(device_t self, int offset, int16_t *val, int rd)
|
||||||
|
{
|
||||||
|
struct wm_softc *sc = device_private(self);
|
||||||
|
uint16_t regnum = BM_PHY_REG_NUM(offset);
|
||||||
|
uint16_t wuce;
|
||||||
|
|
||||||
|
/* XXX Gig must be disabled for MDIO accesses to page 800 */
|
||||||
|
if (sc->sc_type == WM_T_PCH) {
|
||||||
|
/* XXX e1000 driver do nothing... why? */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set page 769 */
|
||||||
|
wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT,
|
||||||
|
BM_WUC_ENABLE_PAGE << BME1000_PAGE_SHIFT);
|
||||||
|
|
||||||
|
wuce = wm_gmii_i82544_readreg(self, 1, BM_WUC_ENABLE_REG);
|
||||||
|
|
||||||
|
wuce &= ~BM_WUC_HOST_WU_BIT;
|
||||||
|
wm_gmii_i82544_writereg(self, 1, BM_WUC_ENABLE_REG,
|
||||||
|
wuce | BM_WUC_ENABLE_BIT);
|
||||||
|
|
||||||
|
/* Select page 800 */
|
||||||
|
wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT,
|
||||||
|
BM_WUC_PAGE << BME1000_PAGE_SHIFT);
|
||||||
|
|
||||||
|
/* Write page 800 */
|
||||||
|
wm_gmii_i82544_writereg(self, 1, BM_WUC_ADDRESS_OPCODE, regnum);
|
||||||
|
|
||||||
|
if (rd)
|
||||||
|
*val = wm_gmii_i82544_readreg(self, 1, BM_WUC_DATA_OPCODE);
|
||||||
|
else
|
||||||
|
wm_gmii_i82544_writereg(self, 1, BM_WUC_DATA_OPCODE, *val);
|
||||||
|
|
||||||
|
/* Set page 769 */
|
||||||
|
wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT,
|
||||||
|
BM_WUC_ENABLE_PAGE << BME1000_PAGE_SHIFT);
|
||||||
|
|
||||||
|
wm_gmii_i82544_writereg(self, 1, BM_WUC_ENABLE_REG, wuce);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* wm_gmii_kv_readreg: [mii interface function]
|
* wm_gmii_hv_readreg: [mii interface function]
|
||||||
*
|
*
|
||||||
* Read a PHY register on the kumeran
|
* Read a PHY register on the kumeran
|
||||||
* This could be handled by the PHY layer if we didn't have to lock the
|
* This could be handled by the PHY layer if we didn't have to lock the
|
||||||
* ressource ...
|
* ressource ...
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
wm_gmii_kv_readreg(device_t self, int phy, int reg)
|
wm_gmii_hv_readreg(device_t self, int phy, int reg)
|
||||||
{
|
{
|
||||||
struct wm_softc *sc = device_private(self);
|
struct wm_softc *sc = device_private(self);
|
||||||
|
uint16_t page = BM_PHY_REG_PAGE(reg);
|
||||||
|
uint16_t regnum = BM_PHY_REG_NUM(reg);
|
||||||
|
uint16_t val;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
if (wm_get_swfw_semaphore(sc, SWFW_PHY0_SM)) {
|
if (wm_get_swfw_semaphore(sc, SWFW_PHY0_SM)) {
|
||||||
|
@ -5472,28 +5583,49 @@ wm_gmii_kv_readreg(device_t self, int phy, int reg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg > GG82563_MAX_REG_ADDRESS) {
|
/* XXX Workaround failure in MDIO access while cable is disconnected */
|
||||||
printf("XXX rd pagesel\n");
|
if (sc->sc_phytype == WMPHY_82577) {
|
||||||
wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT,
|
/* XXX must write */
|
||||||
reg & IGPHY_PAGEMASK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = wm_gmii_i82544_readreg(self, phy, reg & IGPHY_MAXREGADDR);
|
/* Page 800 works differently than the rest so it has its own func */
|
||||||
|
if (page == BM_WUC_PAGE) {
|
||||||
|
wm_access_phy_wakeup_reg_bm(self, reg, &val, 1);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lower than page 768 works differently than the rest so it has its
|
||||||
|
* own func
|
||||||
|
*/
|
||||||
|
if ((page > 0) && (page < HV_INTC_FC_PAGE_START)) {
|
||||||
|
printf("gmii_hv_readreg!!!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (regnum > BME1000_MAX_MULTI_PAGE_REG) {
|
||||||
|
wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT,
|
||||||
|
page << BME1000_PAGE_SHIFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = wm_gmii_i82544_readreg(self, phy, regnum & IGPHY_MAXREGADDR);
|
||||||
wm_put_swfw_semaphore(sc, SWFW_PHY0_SM);
|
wm_put_swfw_semaphore(sc, SWFW_PHY0_SM);
|
||||||
return (rv);
|
return (rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* wm_gmii_kv_writereg: [mii interface function]
|
* wm_gmii_hv_writereg: [mii interface function]
|
||||||
*
|
*
|
||||||
* Write a PHY register on the kumeran.
|
* Write a PHY register on the kumeran.
|
||||||
* This could be handled by the PHY layer if we didn't have to lock the
|
* This could be handled by the PHY layer if we didn't have to lock the
|
||||||
* ressource ...
|
* ressource ...
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
wm_gmii_kv_writereg(device_t self, int phy, int reg, int val)
|
wm_gmii_hv_writereg(device_t self, int phy, int reg, int val)
|
||||||
{
|
{
|
||||||
struct wm_softc *sc = device_private(self);
|
struct wm_softc *sc = device_private(self);
|
||||||
|
uint16_t page = BM_PHY_REG_PAGE(reg);
|
||||||
|
uint16_t regnum = BM_PHY_REG_NUM(reg);
|
||||||
|
|
||||||
if (wm_get_swfw_semaphore(sc, SWFW_PHY0_SM)) {
|
if (wm_get_swfw_semaphore(sc, SWFW_PHY0_SM)) {
|
||||||
aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
|
aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
|
||||||
|
@ -5501,13 +5633,37 @@ wm_gmii_kv_writereg(device_t self, int phy, int reg, int val)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg > GG82563_MAX_REG_ADDRESS) {
|
/* XXX Workaround failure in MDIO access while cable is disconnected */
|
||||||
printf("XXX wr pagesel\n");
|
|
||||||
wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT,
|
/* Page 800 works differently than the rest so it has its own func */
|
||||||
reg & IGPHY_PAGEMASK);
|
if (page == BM_WUC_PAGE) {
|
||||||
|
uint16_t tmp;
|
||||||
|
|
||||||
|
tmp = val;
|
||||||
|
wm_access_phy_wakeup_reg_bm(self, reg, &tmp, 0);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wm_gmii_i82544_writereg(self, phy, reg & IGPHY_MAXREGADDR, val);
|
/*
|
||||||
|
* Lower than page 768 works differently than the rest so it has its
|
||||||
|
* own func
|
||||||
|
*/
|
||||||
|
if ((page > 0) && (page < HV_INTC_FC_PAGE_START)) {
|
||||||
|
printf("gmii_hv_writereg!!!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX Workaround MDIO accesses being disabled after entering IEEE
|
||||||
|
* Power Down (whenever bit 11 of the PHY control register is set)
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (regnum > BME1000_MAX_MULTI_PAGE_REG) {
|
||||||
|
wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT,
|
||||||
|
page << BME1000_PAGE_SHIFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
wm_gmii_i82544_writereg(self, phy, regnum & IGPHY_MAXREGADDR, val);
|
||||||
wm_put_swfw_semaphore(sc, SWFW_PHY0_SM);
|
wm_put_swfw_semaphore(sc, SWFW_PHY0_SM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6289,3 +6445,96 @@ wm_check_for_link(struct wm_softc *sc)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Workaround for pch's PHYs
|
||||||
|
* XXX should be moved to new PHY driver?
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
wm_hv_phy_workaround_ich8lan(struct wm_softc *sc)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* (PCH rev.2) && (82577 && (phy rev 2 or 3)) */
|
||||||
|
|
||||||
|
/* (82577 && (phy rev 1 or 2)) || (82578 & phy rev 1)*/
|
||||||
|
|
||||||
|
/* 82578 */
|
||||||
|
if (sc->sc_phytype == WMPHY_82578) {
|
||||||
|
/* PCH rev. < 3 */
|
||||||
|
if (sc->sc_rev < 3) {
|
||||||
|
/* XXX 6 bit shift? Why? Is it page2? */
|
||||||
|
wm_gmii_hv_writereg(sc->sc_dev, 1, ((1 << 6) | 0x29),
|
||||||
|
0x66c0);
|
||||||
|
wm_gmii_hv_writereg(sc->sc_dev, 1, ((1 << 6) | 0x1e),
|
||||||
|
0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX phy rev. < 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Select page 0 */
|
||||||
|
|
||||||
|
/* XXX acquire semaphore */
|
||||||
|
wm_gmii_i82544_writereg(sc->sc_dev, 1, MII_IGPHY_PAGE_SELECT, 0);
|
||||||
|
/* XXX release semaphore */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Configure the K1 Si workaround during phy reset assuming there is
|
||||||
|
* link so that it disables K1 if link is in 1Gbps.
|
||||||
|
*/
|
||||||
|
wm_k1_gig_workaround_hv(sc, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wm_k1_gig_workaround_hv(struct wm_softc *sc, int link)
|
||||||
|
{
|
||||||
|
int k1_enable = sc->sc_nvm_k1_enabled;
|
||||||
|
|
||||||
|
/* XXX acquire semaphore */
|
||||||
|
|
||||||
|
if (link) {
|
||||||
|
k1_enable = 0;
|
||||||
|
|
||||||
|
/* Link stall fix for link up */
|
||||||
|
wm_gmii_hv_writereg(sc->sc_dev, 1, IGP3_KMRN_DIAG, 0x0100);
|
||||||
|
} else {
|
||||||
|
/* Link stall fix for link down */
|
||||||
|
wm_gmii_hv_writereg(sc->sc_dev, 1, IGP3_KMRN_DIAG, 0x4100);
|
||||||
|
}
|
||||||
|
|
||||||
|
wm_configure_k1_ich8lan(sc, k1_enable);
|
||||||
|
|
||||||
|
/* XXX release semaphore */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wm_configure_k1_ich8lan(struct wm_softc *sc, int k1_enable)
|
||||||
|
{
|
||||||
|
uint32_t ctrl, ctrl_ext, tmp;
|
||||||
|
uint16_t kmrn_reg;
|
||||||
|
|
||||||
|
kmrn_reg = wm_kmrn_readreg(sc, KUMCTRLSTA_OFFSET_K1_CONFIG);
|
||||||
|
|
||||||
|
if (k1_enable)
|
||||||
|
kmrn_reg |= KUMCTRLSTA_K1_ENABLE;
|
||||||
|
else
|
||||||
|
kmrn_reg &= ~KUMCTRLSTA_K1_ENABLE;
|
||||||
|
|
||||||
|
wm_kmrn_writereg(sc, KUMCTRLSTA_OFFSET_K1_CONFIG, kmrn_reg);
|
||||||
|
|
||||||
|
delay(20);
|
||||||
|
|
||||||
|
ctrl = CSR_READ(sc, WMREG_CTRL);
|
||||||
|
ctrl_ext = CSR_READ(sc, WMREG_CTRL_EXT);
|
||||||
|
|
||||||
|
tmp = ctrl & ~(CTRL_SPEED_1000 | CTRL_SPEED_100);
|
||||||
|
tmp |= CTRL_FRCSPD;
|
||||||
|
|
||||||
|
CSR_WRITE(sc, WMREG_CTRL, tmp);
|
||||||
|
CSR_WRITE(sc, WMREG_CTRL_EXT, ctrl_ext | CTRL_EXT_SPD_BYPS);
|
||||||
|
delay(20);
|
||||||
|
|
||||||
|
CSR_WRITE(sc, WMREG_CTRL, ctrl);
|
||||||
|
CSR_WRITE(sc, WMREG_CTRL_EXT, ctrl_ext);
|
||||||
|
delay(20);
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: if_wmreg.h,v 1.34 2010/01/12 22:26:30 msaitoh Exp $ */
|
/* $NetBSD: if_wmreg.h,v 1.35 2010/01/14 18:56:02 msaitoh Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Wasabi Systems, Inc.
|
* Copyright (c) 2001 Wasabi Systems, Inc.
|
||||||
|
@ -276,6 +276,7 @@ struct livengood_tcpip_ctxdesc {
|
||||||
#define EEPROM_OFF_CFG1 0x0a /* config word 1 */
|
#define EEPROM_OFF_CFG1 0x0a /* config word 1 */
|
||||||
#define EEPROM_OFF_CFG2 0x0f /* config word 2 */
|
#define EEPROM_OFF_CFG2 0x0f /* config word 2 */
|
||||||
#define EEPROM_INIT_3GIO_3 0x1a /* PCIe Initial Configuration Word 3 */
|
#define EEPROM_INIT_3GIO_3 0x1a /* PCIe Initial Configuration Word 3 */
|
||||||
|
#define EEPROM_OFF_K1_CONFIG 0x1b /* NVM K1 Config */
|
||||||
#define EEPROM_OFF_SWDPIN 0x20 /* SWD Pins (Cordova) */
|
#define EEPROM_OFF_SWDPIN 0x20 /* SWD Pins (Cordova) */
|
||||||
|
|
||||||
#define EEPROM_CFG1_LVDID (1U << 0)
|
#define EEPROM_CFG1_LVDID (1U << 0)
|
||||||
|
@ -309,6 +310,8 @@ struct livengood_tcpip_ctxdesc {
|
||||||
#define EEPROM_CFG2_SWDPIO_MASK (0xf << EEPROM_CFG2_SWDPIO_SHIFT)
|
#define EEPROM_CFG2_SWDPIO_MASK (0xf << EEPROM_CFG2_SWDPIO_SHIFT)
|
||||||
#define EEPROM_CFG2_MNGM_MASK (3U << 13) /* Manageability Operation mode */
|
#define EEPROM_CFG2_MNGM_MASK (3U << 13) /* Manageability Operation mode */
|
||||||
|
|
||||||
|
#define EEPROM_K1_CONFIG_ENABLE 0x01
|
||||||
|
|
||||||
#define EEPROM_SWDPIN_MASK 0xdf
|
#define EEPROM_SWDPIN_MASK 0xdf
|
||||||
#define EEPROM_SWDPIN_SWDPIN_SHIFT 0
|
#define EEPROM_SWDPIN_SWDPIN_SHIFT 0
|
||||||
#define EEPROM_SWDPIN_SWDPIO_SHIFT 8
|
#define EEPROM_SWDPIN_SWDPIO_SHIFT 8
|
||||||
|
@ -340,6 +343,7 @@ struct livengood_tcpip_ctxdesc {
|
||||||
#define CTRL_EXT_LINK_MODE_TBI 0x00C00000
|
#define CTRL_EXT_LINK_MODE_TBI 0x00C00000
|
||||||
#define CTRL_EXT_LINK_MODE_KMRN 0x00000000
|
#define CTRL_EXT_LINK_MODE_KMRN 0x00000000
|
||||||
#define CTRL_EXT_LINK_MODE_SERDES 0x00C00000
|
#define CTRL_EXT_LINK_MODE_SERDES 0x00C00000
|
||||||
|
#define CTRL_EXT_PHYPDEN 0x00100000
|
||||||
#define CTRL_EXT_DRV_LOAD 0x10000000
|
#define CTRL_EXT_DRV_LOAD 0x10000000
|
||||||
|
|
||||||
|
|
||||||
|
@ -657,6 +661,7 @@ struct livengood_tcpip_ctxdesc {
|
||||||
#define KUMCTRLSTA_OFFSET_INB_CTRL 0x00000002
|
#define KUMCTRLSTA_OFFSET_INB_CTRL 0x00000002
|
||||||
#define KUMCTRLSTA_OFFSET_DIAG 0x00000003
|
#define KUMCTRLSTA_OFFSET_DIAG 0x00000003
|
||||||
#define KUMCTRLSTA_OFFSET_TIMEOUTS 0x00000004
|
#define KUMCTRLSTA_OFFSET_TIMEOUTS 0x00000004
|
||||||
|
#define KUMCTRLSTA_OFFSET_K1_CONFIG 0x00000007
|
||||||
#define KUMCTRLSTA_OFFSET_INB_PARAM 0x00000009
|
#define KUMCTRLSTA_OFFSET_INB_PARAM 0x00000009
|
||||||
#define KUMCTRLSTA_OFFSET_HD_CTRL 0x00000010
|
#define KUMCTRLSTA_OFFSET_HD_CTRL 0x00000010
|
||||||
#define KUMCTRLSTA_OFFSET_M2P_SERDES 0x0000001E
|
#define KUMCTRLSTA_OFFSET_M2P_SERDES 0x0000001E
|
||||||
|
@ -670,6 +675,9 @@ struct livengood_tcpip_ctxdesc {
|
||||||
#define KUMCTRLSTA_INB_CTRL_LINK_TMOUT_DFLT 0x00000500
|
#define KUMCTRLSTA_INB_CTRL_LINK_TMOUT_DFLT 0x00000500
|
||||||
#define KUMCTRLSTA_INB_CTRL_DIS_PADDING 0x00000010
|
#define KUMCTRLSTA_INB_CTRL_DIS_PADDING 0x00000010
|
||||||
|
|
||||||
|
/* K1 Config */
|
||||||
|
#define KUMCTRLSTA_K1_ENABLE 0x0002
|
||||||
|
|
||||||
/* Half-Duplex Control */
|
/* Half-Duplex Control */
|
||||||
#define KUMCTRLSTA_HD_CTRL_10_100_DEFAULT 0x00000004
|
#define KUMCTRLSTA_HD_CTRL_10_100_DEFAULT 0x00000004
|
||||||
#define KUMCTRLSTA_HD_CTRL_1000_DEFAULT 0x00000000
|
#define KUMCTRLSTA_HD_CTRL_1000_DEFAULT 0x00000000
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: if_wmvar.h,v 1.7 2010/01/11 12:29:28 msaitoh Exp $ */
|
/* $NetBSD: if_wmvar.h,v 1.8 2010/01/14 18:56:02 msaitoh Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
|
* Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
|
||||||
|
@ -114,6 +114,21 @@ typedef enum {
|
||||||
WM_T_PCH, /* PCH LAN */
|
WM_T_PCH, /* PCH LAN */
|
||||||
} wm_chip_type;
|
} wm_chip_type;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
WMPHY_UNKNOWN = 0,
|
||||||
|
WMPHY_NONE,
|
||||||
|
WMPHY_M88,
|
||||||
|
WMPHY_IGP,
|
||||||
|
WMPHY_IGP_2,
|
||||||
|
WMPHY_GG82563,
|
||||||
|
WMPHY_IGP_3,
|
||||||
|
WMPHY_IFE,
|
||||||
|
WMPHY_BM,
|
||||||
|
WMPHY_82578,
|
||||||
|
WMPHY_82577
|
||||||
|
} wm_phy_type;
|
||||||
|
|
||||||
|
|
||||||
#define WM_PHY_CFG_TIMEOUT 100
|
#define WM_PHY_CFG_TIMEOUT 100
|
||||||
#define WM_ICH8_LAN_INIT_TIMEOUT 1500
|
#define WM_ICH8_LAN_INIT_TIMEOUT 1500
|
||||||
#define WM_MDIO_OWNERSHIP_TIMEOUT 10
|
#define WM_MDIO_OWNERSHIP_TIMEOUT 10
|
||||||
|
|
Loading…
Reference in New Issue