Sync with Intel's original em driver:
- Add dspcode for igp3 and use it when the EEPROM isn't available. - Add some delays. - Stop the PHY transmitter before patching the DSP code and restart it after wrote. - Save and restore register 0x2f5b.
This commit is contained in:
parent
7a92e8e89d
commit
05b467b58c
sys/dev
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: igphy.c,v 1.19 2009/12/16 04:50:35 msaitoh Exp $ */
|
||||
/* $NetBSD: igphy.c,v 1.20 2009/12/16 14:37:26 msaitoh Exp $ */
|
||||
|
||||
/*
|
||||
* The Intel copyright applies to the analog register setup, and the
|
||||
@ -70,7 +70,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: igphy.c,v 1.19 2009/12/16 04:50:35 msaitoh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: igphy.c,v 1.20 2009/12/16 14:37:26 msaitoh Exp $");
|
||||
|
||||
#include "opt_mii.h"
|
||||
|
||||
@ -94,10 +94,12 @@ struct igphy_softc {
|
||||
struct mii_softc sc_mii;
|
||||
int sc_smartspeed;
|
||||
uint32_t sc_mactype;
|
||||
uint32_t sc_macflags;
|
||||
};
|
||||
|
||||
static void igphy_reset(struct mii_softc *);
|
||||
static void igphy_load_dspcode(struct mii_softc *);
|
||||
static void igphy_load_dspcode_igp3(struct mii_softc *);
|
||||
static void igphy_smartspeed_workaround(struct mii_softc *sc);
|
||||
|
||||
static int igphymatch(device_t, cfdata_t, void *);
|
||||
@ -152,6 +154,8 @@ igphyattach(device_t parent, device_t self, void *aux)
|
||||
dict = device_properties(parent);
|
||||
if (!prop_dictionary_get_uint32(dict, "mactype", &igsc->sc_mactype))
|
||||
aprint_error("WARNING! Failed to get mactype\n");
|
||||
if (!prop_dictionary_get_uint32(dict, "macflags", &igsc->sc_macflags))
|
||||
aprint_error("WARNING! Failed to get macflags\n");
|
||||
|
||||
sc->mii_dev = self;
|
||||
sc->mii_inst = mii->mii_instance;
|
||||
@ -176,62 +180,127 @@ igphyattach(device_t parent, device_t self, void *aux)
|
||||
aprint_normal("\n");
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int reg;
|
||||
uint16_t val;
|
||||
} dspcode;
|
||||
|
||||
static const dspcode igp1code[] = {
|
||||
{ 0x1f95, 0x0001 },
|
||||
{ 0x1f71, 0xbd21 },
|
||||
{ 0x1f79, 0x0018 },
|
||||
{ 0x1f30, 0x1600 },
|
||||
{ 0x1f31, 0x0014 },
|
||||
{ 0x1f32, 0x161c },
|
||||
{ 0x1f94, 0x0003 },
|
||||
{ 0x1f96, 0x003f },
|
||||
{ 0x2010, 0x0008 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
static const dspcode igp1code_r2[] = {
|
||||
{ 0x1f73, 0x0099 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
static const dspcode igp3code[] = {
|
||||
{ 0x2f5b, 0x9018},
|
||||
{ 0x2f52, 0x0000},
|
||||
{ 0x2fb1, 0x8b24},
|
||||
{ 0x2fb2, 0xf8f0},
|
||||
{ 0x2010, 0x10b0},
|
||||
{ 0x2011, 0x0000},
|
||||
{ 0x20dd, 0x249a},
|
||||
{ 0x20de, 0x00d3},
|
||||
{ 0x28b4, 0x04ce},
|
||||
{ 0x2f70, 0x29e4},
|
||||
{ 0x0000, 0x0140},
|
||||
{ 0x1f30, 0x1606},
|
||||
{ 0x1f31, 0xb814},
|
||||
{ 0x1f35, 0x002a},
|
||||
{ 0x1f3e, 0x0067},
|
||||
{ 0x1f54, 0x0065},
|
||||
{ 0x1f55, 0x002a},
|
||||
{ 0x1f56, 0x002a},
|
||||
{ 0x1f72, 0x3fb0},
|
||||
{ 0x1f76, 0xc0ff},
|
||||
{ 0x1f77, 0x1dec},
|
||||
{ 0x1f78, 0xf9ef},
|
||||
{ 0x1f79, 0x0210},
|
||||
{ 0x1895, 0x0003},
|
||||
{ 0x1796, 0x0008},
|
||||
{ 0x1798, 0xd008},
|
||||
{ 0x1898, 0xd918},
|
||||
{ 0x187a, 0x0800},
|
||||
{ 0x0019, 0x008d},
|
||||
{ 0x001b, 0x2080},
|
||||
{ 0x0014, 0x0045},
|
||||
{ 0x0000, 0x1340},
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
/* DSP patch for igp1 and igp2 */
|
||||
static void
|
||||
igphy_load_dspcode(struct mii_softc *sc)
|
||||
{
|
||||
struct igphy_softc *igsc = (struct igphy_softc *) sc;
|
||||
static const struct {
|
||||
int reg;
|
||||
uint16_t val;
|
||||
} dspcode[] = {
|
||||
{ 0x1f95, 0x0001 },
|
||||
{ 0x1f71, 0xbd21 },
|
||||
{ 0x1f79, 0x0018 },
|
||||
{ 0x1f30, 0x1600 },
|
||||
{ 0x1f31, 0x0014 },
|
||||
{ 0x1f32, 0x161c },
|
||||
{ 0x1f94, 0x0003 },
|
||||
{ 0x1f96, 0x003f },
|
||||
{ 0x2010, 0x0008 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
const dspcode *code;
|
||||
uint16_t reg;
|
||||
int i;
|
||||
|
||||
/* This workaround is only for 82541 and 82547 */
|
||||
switch (igsc->sc_mactype) {
|
||||
case WM_T_82541:
|
||||
case WM_T_82547:
|
||||
code = igp1code;
|
||||
break;
|
||||
case WM_T_82541_2:
|
||||
case WM_T_82547_2:
|
||||
code = igp1code_r2;
|
||||
break;
|
||||
default:
|
||||
/* byebye */
|
||||
return;
|
||||
return; /* byebye */
|
||||
}
|
||||
|
||||
delay(10);
|
||||
/* Delay after phy reset to enable NVM configuration to load */
|
||||
delay(20000);
|
||||
|
||||
/*
|
||||
* Save off the current value of register 0x2F5B to be restored at
|
||||
* the end of this routine.
|
||||
*/
|
||||
reg = IGPHY_READ(sc, 0x2f5b);
|
||||
|
||||
/* Disabled the PHY transmitter */
|
||||
IGPHY_WRITE(sc, 0x2f5b, 0x0003);
|
||||
|
||||
delay(20000);
|
||||
|
||||
PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, 0x0000);
|
||||
PHY_WRITE(sc, 0x0000, 0x0140);
|
||||
|
||||
delay(5);
|
||||
delay(5000);
|
||||
|
||||
switch (igsc->sc_mactype) {
|
||||
case WM_T_82541:
|
||||
case WM_T_82547:
|
||||
for (i = 0; dspcode[i].reg != 0; i++)
|
||||
IGPHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
|
||||
break;
|
||||
case WM_T_82541_2:
|
||||
case WM_T_82547_2:
|
||||
IGPHY_WRITE(sc, 0x1f73, 0x0099);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
for (i = 0; !((code[i].reg == 0) && (code[i].val == 0)); i++)
|
||||
IGPHY_WRITE(sc, code[i].reg, code[i].val);
|
||||
|
||||
PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT,0x0000);
|
||||
PHY_WRITE(sc, 0x0000, 0x3300);
|
||||
|
||||
delay(20000);
|
||||
|
||||
/* Now enable the transmitter */
|
||||
IGPHY_WRITE(sc, 0x2f5b, reg);
|
||||
}
|
||||
|
||||
static void
|
||||
igphy_load_dspcode_igp3(struct mii_softc *sc)
|
||||
{
|
||||
const dspcode *code = igp3code;
|
||||
int i;
|
||||
|
||||
for (i = 0; !((code[i].reg == 0) && (code[i].val == 0)); i++)
|
||||
IGPHY_WRITE(sc, code[i].reg, code[i].val);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -241,7 +310,23 @@ igphy_reset(struct mii_softc *sc)
|
||||
uint16_t fused, fine, coarse;
|
||||
|
||||
mii_phy_reset(sc);
|
||||
igphy_load_dspcode(sc);
|
||||
delay(150);
|
||||
|
||||
switch (igsc->sc_mactype) {
|
||||
case WM_T_82541:
|
||||
case WM_T_82547:
|
||||
case WM_T_82541_2:
|
||||
case WM_T_82547_2:
|
||||
igphy_load_dspcode(sc);
|
||||
break;
|
||||
case WM_T_ICH8:
|
||||
case WM_T_ICH9:
|
||||
if ((igsc->sc_macflags & WM_F_EEPROM_INVALID) != 0)
|
||||
igphy_load_dspcode_igp3(sc);
|
||||
break;
|
||||
default: /* Not for ICH10, PCH and 8257[12] */
|
||||
break;
|
||||
}
|
||||
|
||||
if (igsc->sc_mactype == WM_T_82547) {
|
||||
fused = IGPHY_READ(sc, MII_IGPHY_ANALOG_SPARE_FUSE_STATUS);
|
||||
@ -266,7 +351,7 @@ igphy_reset(struct mii_softc *sc)
|
||||
ANALOG_FUSE_ENABLE_SW_CONTROL);
|
||||
}
|
||||
}
|
||||
PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT,0x0000);
|
||||
PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, 0x0000);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: if_wm.c,v 1.182 2009/12/16 04:50:35 msaitoh Exp $ */
|
||||
/* $NetBSD: if_wm.c,v 1.183 2009/12/16 14:37:26 msaitoh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
|
||||
@ -76,7 +76,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.182 2009/12/16 04:50:35 msaitoh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.183 2009/12/16 14:37:26 msaitoh Exp $");
|
||||
|
||||
#include "bpfilter.h"
|
||||
#include "rnd.h"
|
||||
@ -380,22 +380,6 @@ do { \
|
||||
(sc)->sc_rxtailp = &(m)->m_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/* sc_flags */
|
||||
#define WM_F_HAS_MII 0x0001 /* has MII */
|
||||
#define WM_F_EEPROM_HANDSHAKE 0x0002 /* requires EEPROM handshake */
|
||||
#define WM_F_EEPROM_SEMAPHORE 0x0004 /* EEPROM with semaphore */
|
||||
#define WM_F_EEPROM_EERDEEWR 0x0008 /* EEPROM access via EERD/EEWR */
|
||||
#define WM_F_EEPROM_SPI 0x0010 /* EEPROM is SPI */
|
||||
#define WM_F_EEPROM_FLASH 0x0020 /* EEPROM is FLASH */
|
||||
#define WM_F_EEPROM_INVALID 0x0040 /* EEPROM not present (bad checksum) */
|
||||
#define WM_F_IOH_VALID 0x0080 /* I/O handle is valid */
|
||||
#define WM_F_BUS64 0x0100 /* bus is 64-bit */
|
||||
#define WM_F_PCIX 0x0200 /* bus is PCI-X */
|
||||
#define WM_F_CSA 0x0400 /* bus is CSA */
|
||||
#define WM_F_PCIE 0x0800 /* bus is PCI-Express */
|
||||
#define WM_F_SWFW_SYNC 0x1000 /* Software-Firmware synchronisation */
|
||||
#define WM_F_SWFWHW_SYNC 0x2000 /* Software-Firmware synchronisation */
|
||||
|
||||
#ifdef WM_EVENT_COUNTERS
|
||||
#define WM_EVCNT_INCR(ev) (ev)->ev_count++
|
||||
#define WM_EVCNT_ADD(ev, val) (ev)->ev_count += (val)
|
||||
@ -981,7 +965,7 @@ wm_attach(device_t parent, device_t self, void *aux)
|
||||
sc->sc_type = WM_T_82542_2_0;
|
||||
}
|
||||
|
||||
/* Set device properties */
|
||||
/* Set device properties (mactype)*/
|
||||
dict = device_properties(sc->sc_dev);
|
||||
prop_dictionary_set_uint32(dict, "mactype", sc->sc_type);
|
||||
|
||||
@ -1351,18 +1335,26 @@ wm_attach(device_t parent, device_t self, void *aux)
|
||||
* that no EEPROM is attached.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Validate the EEPROM checksum. If the checksum fails, flag this for
|
||||
* later, so we can fail future reads from the EEPROM.
|
||||
*/
|
||||
if (wm_validate_eeprom_checksum(sc)) {
|
||||
/* Check whether EEPROM is present or not */
|
||||
if ((CSR_READ(sc, WMREG_EECD) & EECD_EE_PRES) == 0) {
|
||||
/* Not found */
|
||||
sc->sc_flags |= WM_F_EEPROM_INVALID;
|
||||
} else {
|
||||
/*
|
||||
* Read twice again because some PCI-e parts fail the first
|
||||
* check due to the link being in sleep state.
|
||||
* Validate the EEPROM checksum. If the checksum fails, flag
|
||||
* this for later, so we can fail future reads from the EEPROM.
|
||||
*/
|
||||
if (wm_validate_eeprom_checksum(sc))
|
||||
sc->sc_flags |= WM_F_EEPROM_INVALID;
|
||||
if (wm_validate_eeprom_checksum(sc)) {
|
||||
/*
|
||||
* Read twice again because some PCI-e parts fail the
|
||||
* first check due to the link being in sleep state.
|
||||
*/
|
||||
if (wm_validate_eeprom_checksum(sc))
|
||||
sc->sc_flags |= WM_F_EEPROM_INVALID;
|
||||
}
|
||||
}
|
||||
/* Set device properties (macflags)*/
|
||||
prop_dictionary_set_uint32(dict, "macflags", sc->sc_flags);
|
||||
|
||||
if (sc->sc_flags & WM_F_EEPROM_INVALID)
|
||||
aprint_verbose_dev(sc->sc_dev, "No EEPROM\n");
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: if_wmvar.h,v 1.3 2009/12/16 04:50:36 msaitoh Exp $ */
|
||||
/* $NetBSD: if_wmvar.h,v 1.4 2009/12/16 14:37:26 msaitoh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
|
||||
@ -71,6 +71,22 @@
|
||||
#ifndef _DEV_PCI_IF_WMVAR_H_
|
||||
#define _DEV_PCI_IF_WMVAR_H_
|
||||
|
||||
/* sc_flags */
|
||||
#define WM_F_HAS_MII 0x0001 /* has MII */
|
||||
#define WM_F_EEPROM_HANDSHAKE 0x0002 /* requires EEPROM handshake */
|
||||
#define WM_F_EEPROM_SEMAPHORE 0x0004 /* EEPROM with semaphore */
|
||||
#define WM_F_EEPROM_EERDEEWR 0x0008 /* EEPROM access via EERD/EEWR */
|
||||
#define WM_F_EEPROM_SPI 0x0010 /* EEPROM is SPI */
|
||||
#define WM_F_EEPROM_FLASH 0x0020 /* EEPROM is FLASH */
|
||||
#define WM_F_EEPROM_INVALID 0x0040 /* EEPROM not present (bad checksum) */
|
||||
#define WM_F_IOH_VALID 0x0080 /* I/O handle is valid */
|
||||
#define WM_F_BUS64 0x0100 /* bus is 64-bit */
|
||||
#define WM_F_PCIX 0x0200 /* bus is PCI-X */
|
||||
#define WM_F_CSA 0x0400 /* bus is CSA */
|
||||
#define WM_F_PCIE 0x0800 /* bus is PCI-Express */
|
||||
#define WM_F_SWFW_SYNC 0x1000 /* Software-Firmware synchronisation */
|
||||
#define WM_F_SWFWHW_SYNC 0x2000 /* Software-Firmware synchronisation */
|
||||
|
||||
typedef enum {
|
||||
WM_T_unknown = 0,
|
||||
WM_T_82542_2_0, /* i82542 2.0 (really old) */
|
||||
|
Loading…
x
Reference in New Issue
Block a user