Updated msk and related mii to current freebsd head.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33716 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Adrien Destugues
2009-10-21 20:37:18 +00:00
parent e78ad19f6b
commit 63b04e111b
5 changed files with 75 additions and 28 deletions
@@ -29,7 +29,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE. * THE POSSIBILITY OF SUCH DAMAGE.
* *
* $FreeBSD: src/sys/dev/mii/brgphyreg.h,v 1.6.2.2 2007/06/14 21:07:19 davidch Exp $ * $FreeBSD$
*/ */
#ifndef _DEV_MII_BRGPHYREG_H_ #ifndef _DEV_MII_BRGPHYREG_H_
@@ -161,6 +161,7 @@
#define BRGPHY_MII_DSP_RW_PORT 0x15 /* DSP coefficient r/w port */ #define BRGPHY_MII_DSP_RW_PORT 0x15 /* DSP coefficient r/w port */
#define BRGPHY_MII_DSP_ADDR_REG 0x17 /* DSP coefficient addr register */ #define BRGPHY_MII_DSP_ADDR_REG 0x17 /* DSP coefficient addr register */
#define BRGPHY_MII_EPHY_PTEST 0x17 /* 5906 PHY register */
#define BRGPHY_DSP_TAP_NUMBER_MASK 0x00 #define BRGPHY_DSP_TAP_NUMBER_MASK 0x00
#define BRGPHY_DSP_AGC_A 0x00 #define BRGPHY_DSP_AGC_A 0x00
@@ -59,6 +59,9 @@ __FBSDID("$FreeBSD$");
#include "miidevs.h" #include "miidevs.h"
#include <dev/mii/e1000phyreg.h> #include <dev/mii/e1000phyreg.h>
/* XXX */
#include <machine/bus.h>
#include <dev/msk/if_mskreg.h>
#include "miibus_if.h" #include "miibus_if.h"
@@ -68,6 +71,7 @@ static int e1000phy_attach(device_t);
struct e1000phy_softc { struct e1000phy_softc {
struct mii_softc mii_sc; struct mii_softc mii_sc;
int mii_model; int mii_model;
struct msk_mii_data *mmd;
}; };
static device_method_t e1000phy_methods[] = { static device_method_t e1000phy_methods[] = {
@@ -130,6 +134,7 @@ e1000phy_attach(device_t dev)
struct mii_softc *sc; struct mii_softc *sc;
struct mii_attach_args *ma; struct mii_attach_args *ma;
struct mii_data *mii; struct mii_data *mii;
struct ifnet *ifp;
esc = device_get_softc(dev); esc = device_get_softc(dev);
sc = &esc->mii_sc; sc = &esc->mii_sc;
@@ -145,6 +150,16 @@ e1000phy_attach(device_t dev)
mii->mii_instance++; mii->mii_instance++;
esc->mii_model = MII_MODEL(ma->mii_id2); esc->mii_model = MII_MODEL(ma->mii_id2);
ifp = sc->mii_pdata->mii_ifp;
if (strcmp(ifp->if_dname, "msk") == 0) {
/* XXX */
esc->mmd = device_get_ivars(
device_get_parent(device_get_parent(dev)));
if (esc->mmd != NULL &&
(esc->mmd->mii_flags & MIIF_HAVEFIBER) != 0)
sc->mii_flags |= MIIF_HAVEFIBER;
}
switch (esc->mii_model) { switch (esc->mii_model) {
case MII_MODEL_MARVELL_E1011: case MII_MODEL_MARVELL_E1011:
case MII_MODEL_MARVELL_E1112: case MII_MODEL_MARVELL_E1112:
@@ -199,6 +214,13 @@ e1000phy_reset(struct mii_softc *sc)
reg &= ~E1000_SCR_MODE_MASK; reg &= ~E1000_SCR_MODE_MASK;
reg |= E1000_SCR_MODE_1000BX; reg |= E1000_SCR_MODE_1000BX;
PHY_WRITE(sc, E1000_SCR, reg); PHY_WRITE(sc, E1000_SCR, reg);
if (esc->mmd != NULL && esc->mmd->pmd == 'P') {
/* Set SIGDET polarity low for SFP module. */
PHY_WRITE(sc, E1000_EADR, 1);
reg = PHY_READ(sc, E1000_SCR);
reg |= E1000_SCR_FIB_SIGDET_POLARITY;
PHY_WRITE(sc, E1000_SCR, reg);
}
PHY_WRITE(sc, E1000_EADR, page); PHY_WRITE(sc, E1000_EADR, page);
} }
} else { } else {
@@ -240,17 +262,15 @@ e1000phy_reset(struct mii_softc *sc)
if (esc->mii_model == MII_MODEL_MARVELL_E1116 || if (esc->mii_model == MII_MODEL_MARVELL_E1116 ||
esc->mii_model == MII_MODEL_MARVELL_E1149) { esc->mii_model == MII_MODEL_MARVELL_E1149) {
page = PHY_READ(sc, E1000_EADR);
/* Select page 2, MAC specific control register. */
PHY_WRITE(sc, E1000_EADR, 2); PHY_WRITE(sc, E1000_EADR, 2);
reg = PHY_READ(sc, E1000_SCR); reg = PHY_READ(sc, E1000_SCR);
reg |= E1000_SCR_RGMII_POWER_UP; reg |= E1000_SCR_RGMII_POWER_UP;
PHY_WRITE(sc, E1000_SCR, reg); PHY_WRITE(sc, E1000_SCR, reg);
PHY_WRITE(sc, E1000_EADR, page); PHY_WRITE(sc, E1000_EADR, 0);
} }
} }
switch (MII_MODEL(esc->mii_model)) { switch (esc->mii_model) {
case MII_MODEL_MARVELL_E3082: case MII_MODEL_MARVELL_E3082:
case MII_MODEL_MARVELL_E1112: case MII_MODEL_MARVELL_E1112:
case MII_MODEL_MARVELL_E1118: case MII_MODEL_MARVELL_E1118:
@@ -487,8 +507,11 @@ e1000phy_status(struct mii_softc *sc)
return; return;
} }
} else { } else {
if (ssr & E1000_SSR_1000MBS) /*
mii->mii_media_active |= IFM_1000_SX; * Some fiber PHY(88E1112) does not seem to set resolved
* speed so always assume we've got IFM_1000_SX.
*/
mii->mii_media_active |= IFM_1000_SX;
} }
if (ssr & E1000_SSR_DUPLEX) if (ssr & E1000_SSR_DUPLEX)
@@ -248,6 +248,11 @@
#define E1000_SCR_EN_DETECT_MASK 0x0300 #define E1000_SCR_EN_DETECT_MASK 0x0300
/* 88E1112 page 1 fiber specific control */
#define E1000_SCR_FIB_TX_DIS 0x0008
#define E1000_SCR_FIB_SIGDET_POLARITY 0x0200
#define E1000_SCR_FIB_FORCE_LINK 0x0400
/* 88E1112 page 2 */ /* 88E1112 page 2 */
#define E1000_SCR_MODE_MASK 0x0380 #define E1000_SCR_MODE_MASK 0x0380
#define E1000_SCR_MODE_AUTO 0x0180 #define E1000_SCR_MODE_AUTO 0x0180
@@ -223,6 +223,8 @@ static struct msk_product {
"Marvell Yukon 88E8072 Gigabit Ethernet" }, "Marvell Yukon 88E8072 Gigabit Ethernet" },
{ VENDORID_DLINK, DEVICEID_DLINK_DGE550SX, { VENDORID_DLINK, DEVICEID_DLINK_DGE550SX,
"D-Link 550SX Gigabit Ethernet" }, "D-Link 550SX Gigabit Ethernet" },
{ VENDORID_DLINK, DEVICEID_DLINK_DGE560SX,
"D-Link 560SX Gigabit Ethernet" },
{ VENDORID_DLINK, DEVICEID_DLINK_DGE560T, { VENDORID_DLINK, DEVICEID_DLINK_DGE560T,
"D-Link 560T Gigabit Ethernet" } "D-Link 560T Gigabit Ethernet" }
}; };
@@ -601,7 +603,7 @@ msk_rxfilter(struct msk_if_softc *sc_if)
mchash[1] = 0xffff; mchash[1] = 0xffff;
} else { } else {
mode |= GM_RXCR_UCF_ENA; mode |= GM_RXCR_UCF_ENA;
IF_ADDR_LOCK(ifp); if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK) if (ifma->ifma_addr->sa_family != AF_LINK)
continue; continue;
@@ -612,7 +614,7 @@ msk_rxfilter(struct msk_if_softc *sc_if)
/* Set the corresponding bit in the hash table. */ /* Set the corresponding bit in the hash table. */
mchash[crc >> 5] |= 1 << (crc & 0x1f); mchash[crc >> 5] |= 1 << (crc & 0x1f);
} }
IF_ADDR_UNLOCK(ifp); if_maddr_runlock(ifp);
if (mchash[0] != 0 || mchash[1] != 0) if (mchash[0] != 0 || mchash[1] != 0)
mode |= GM_RXCR_MCF_ENA; mode |= GM_RXCR_MCF_ENA;
} }
@@ -1445,6 +1447,7 @@ msk_attach(device_t dev)
struct msk_softc *sc; struct msk_softc *sc;
struct msk_if_softc *sc_if; struct msk_if_softc *sc_if;
struct ifnet *ifp; struct ifnet *ifp;
struct msk_mii_data *mmd;
int i, port, error; int i, port, error;
uint8_t eaddr[6]; uint8_t eaddr[6];
@@ -1454,7 +1457,8 @@ msk_attach(device_t dev)
error = 0; error = 0;
sc_if = device_get_softc(dev); sc_if = device_get_softc(dev);
sc = device_get_softc(device_get_parent(dev)); sc = device_get_softc(device_get_parent(dev));
port = *(int *)device_get_ivars(dev); mmd = device_get_ivars(dev);
port = mmd->port;
sc_if->msk_if_dev = dev; sc_if->msk_if_dev = dev;
sc_if->msk_port = port; sc_if->msk_port = port;
@@ -1600,7 +1604,8 @@ static int
mskc_attach(device_t dev) mskc_attach(device_t dev)
{ {
struct msk_softc *sc; struct msk_softc *sc;
int error, msic, msir, *port, reg; struct msk_mii_data *mmd;
int error, msic, msir, reg;
sc = device_get_softc(dev); sc = device_get_softc(dev);
sc->msk_dev = dev; sc->msk_dev = dev;
@@ -1669,10 +1674,6 @@ mskc_attach(device_t dev)
CSR_WRITE_2(sc, B0_CTST, CS_RST_SET); CSR_WRITE_2(sc, B0_CTST, CS_RST_SET);
CSR_WRITE_2(sc, B0_CTST, CS_RST_CLR); CSR_WRITE_2(sc, B0_CTST, CS_RST_CLR);
sc->msk_pmd = CSR_READ_1(sc, B2_PMD_TYP); sc->msk_pmd = CSR_READ_1(sc, B2_PMD_TYP);
if (sc->msk_pmd == 'L' || sc->msk_pmd == 'S')
sc->msk_coppertype = 0;
else
sc->msk_coppertype = 1;
/* Check number of MACs. */ /* Check number of MACs. */
sc->msk_num_port = 1; sc->msk_num_port = 1;
if ((CSR_READ_1(sc, B2_Y2_HW_RES) & CFG_DUAL_MAC_MSK) == if ((CSR_READ_1(sc, B2_Y2_HW_RES) & CFG_DUAL_MAC_MSK) ==
@@ -1812,15 +1813,18 @@ mskc_attach(device_t dev)
error = ENXIO; error = ENXIO;
goto fail; goto fail;
} }
port = malloc(sizeof(int), M_DEVBUF, M_WAITOK); mmd = malloc(sizeof(struct msk_mii_data), M_DEVBUF, M_WAITOK | M_ZERO);
if (port == NULL) { if (mmd == NULL) {
device_printf(dev, "failed to allocate memory for " device_printf(dev, "failed to allocate memory for "
"ivars of PORT_A\n"); "ivars of PORT_A\n");
error = ENXIO; error = ENXIO;
goto fail; goto fail;
} }
*port = MSK_PORT_A; mmd->port = MSK_PORT_A;
device_set_ivars(sc->msk_devs[MSK_PORT_A], port); mmd->pmd = sc->msk_pmd;
if (sc->msk_pmd == 'L' || sc->msk_pmd == 'S' || sc->msk_pmd == 'P')
mmd->mii_flags |= MIIF_HAVEFIBER;
device_set_ivars(sc->msk_devs[MSK_PORT_A], mmd);
if (sc->msk_num_port > 1) { if (sc->msk_num_port > 1) {
sc->msk_devs[MSK_PORT_B] = device_add_child(dev, "msk", -1); sc->msk_devs[MSK_PORT_B] = device_add_child(dev, "msk", -1);
@@ -1829,15 +1833,18 @@ mskc_attach(device_t dev)
error = ENXIO; error = ENXIO;
goto fail; goto fail;
} }
port = malloc(sizeof(int), M_DEVBUF, M_WAITOK); mmd = malloc(sizeof(struct msk_mii_data), M_DEVBUF, M_WAITOK | M_ZERO);
if (port == NULL) { if (mmd == NULL) {
device_printf(dev, "failed to allocate memory for " device_printf(dev, "failed to allocate memory for "
"ivars of PORT_B\n"); "ivars of PORT_B\n");
error = ENXIO; error = ENXIO;
goto fail; goto fail;
} }
*port = MSK_PORT_B; mmd->port = MSK_PORT_B;
device_set_ivars(sc->msk_devs[MSK_PORT_B], port); mmd->pmd = sc->msk_pmd;
if (sc->msk_pmd == 'L' || sc->msk_pmd == 'S' || sc->msk_pmd == 'P')
mmd->mii_flags |= MIIF_HAVEFIBER;
device_set_ivars(sc->msk_devs[MSK_PORT_B], mmd);
} }
error = bus_generic_attach(dev); error = bus_generic_attach(dev);
@@ -3794,9 +3801,14 @@ msk_init_locked(struct msk_if_softc *sc_if)
/* Set receive filter. */ /* Set receive filter. */
msk_rxfilter(sc_if); msk_rxfilter(sc_if);
/* Flush Rx MAC FIFO on any flow control or error. */ if (sc->msk_hw_id == CHIP_ID_YUKON_XL) {
CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_FL_MSK), /* Clear flush mask - HW bug. */
GMR_FS_ANY_ERR); CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_FL_MSK), 0);
} else {
/* Flush Rx MAC FIFO on any flow control or error. */
CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_FL_MSK),
GMR_FS_ANY_ERR);
}
/* /*
* Set Rx FIFO flush threshold to 64 bytes + 1 FIFO word * Set Rx FIFO flush threshold to 64 bytes + 1 FIFO word
@@ -4188,7 +4200,7 @@ msk_stats_clear(struct msk_if_softc *sc_if)
gmac = GMAC_READ_2(sc, sc_if->msk_port, GM_PHY_ADDR); gmac = GMAC_READ_2(sc, sc_if->msk_port, GM_PHY_ADDR);
GMAC_WRITE_2(sc, sc_if->msk_port, GM_PHY_ADDR, gmac | GM_PAR_MIB_CLR); GMAC_WRITE_2(sc, sc_if->msk_port, GM_PHY_ADDR, gmac | GM_PAR_MIB_CLR);
/* Read all MIB Counters with Clear Mode set. */ /* Read all MIB Counters with Clear Mode set. */
for (i = GM_RXF_UC_OK; i <= GM_TXE_FIFO_UR; i++) for (i = GM_RXF_UC_OK; i <= GM_TXE_FIFO_UR; i += sizeof(uint32_t))
reg = MSK_READ_MIB32(sc_if->msk_port, i); reg = MSK_READ_MIB32(sc_if->msk_port, i);
/* Clear MIB Clear Counter Mode. */ /* Clear MIB Clear Counter Mode. */
gmac &= ~GM_PAR_MIB_CLR; gmac &= ~GM_PAR_MIB_CLR;
@@ -148,6 +148,7 @@
* D-Link gigabit ethernet device ID * D-Link gigabit ethernet device ID
*/ */
#define DEVICEID_DLINK_DGE550SX 0x4001 #define DEVICEID_DLINK_DGE550SX 0x4001
#define DEVICEID_DLINK_DGE560SX 0x4002
#define DEVICEID_DLINK_DGE560T 0x4b00 #define DEVICEID_DLINK_DGE560T 0x4b00
#define BIT_31 (1 << 31) #define BIT_31 (1 << 31)
@@ -2403,6 +2404,12 @@ struct msk_ring_data {
#define MSK_TX_TIMEOUT 5 #define MSK_TX_TIMEOUT 5
#define MSK_PUT_WM 10 #define MSK_PUT_WM 10
struct msk_mii_data {
int port;
uint32_t pmd;
int mii_flags;
};
/* Forward decl. */ /* Forward decl. */
struct msk_if_softc; struct msk_if_softc;
@@ -2466,7 +2473,6 @@ struct msk_softc {
uint8_t msk_num_port; uint8_t msk_num_port;
int msk_ramsize; /* amount of SRAM on NIC */ int msk_ramsize; /* amount of SRAM on NIC */
uint32_t msk_pmd; /* physical media type */ uint32_t msk_pmd; /* physical media type */
uint32_t msk_coppertype;
uint32_t msk_intrmask; uint32_t msk_intrmask;
uint32_t msk_intrhwemask; uint32_t msk_intrhwemask;
uint32_t msk_pflags; uint32_t msk_pflags;