Skip to content

Commit

Permalink
MFC 197590.
Browse files Browse the repository at this point in the history
  Add hack to pass controller specific information to phy driver.
  Unlike most other PHYs there is no easy way to know which media
  type the PHY supports on Marvell PHYs. MIIF_HAVEFIBER flags is now
  passed via bus-specific instance variable of a device. While I'm
  here add 88E1112 specific work around to set SIGDET polarity low.
  Many thanks "Eugene Perevyazko <john <> dnepro dot net>" who kindly
  gave remote access to system with DGE-560SX.
  • Loading branch information
yongari authored and yongari committed Nov 29, 2009
1 parent f016763 commit 2ba2cfc
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 15 deletions.
22 changes: 22 additions & 0 deletions sys/dev/mii/e1000phy.c
Expand Up @@ -59,6 +59,9 @@ __FBSDID("$FreeBSD$");
#include "miidevs.h"

#include <dev/mii/e1000phyreg.h>
/* XXX */
#include <machine/bus.h>
#include <dev/msk/if_mskreg.h>

#include "miibus_if.h"

Expand All @@ -68,6 +71,7 @@ static int e1000phy_attach(device_t);
struct e1000phy_softc {
struct mii_softc mii_sc;
int mii_model;
struct msk_mii_data *mmd;
};

static device_method_t e1000phy_methods[] = {
Expand Down Expand Up @@ -130,6 +134,7 @@ e1000phy_attach(device_t dev)
struct mii_softc *sc;
struct mii_attach_args *ma;
struct mii_data *mii;
struct ifnet *ifp;

esc = device_get_softc(dev);
sc = &esc->mii_sc;
Expand All @@ -145,6 +150,16 @@ e1000phy_attach(device_t dev)
mii->mii_instance++;

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) {
case MII_MODEL_MARVELL_E1011:
case MII_MODEL_MARVELL_E1112:
Expand Down Expand Up @@ -199,6 +214,13 @@ e1000phy_reset(struct mii_softc *sc)
reg &= ~E1000_SCR_MODE_MASK;
reg |= E1000_SCR_MODE_1000BX;
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);
}
} else {
Expand Down
5 changes: 5 additions & 0 deletions sys/dev/mii/e1000phyreg.h
Expand Up @@ -248,6 +248,11 @@

#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 */
#define E1000_SCR_MODE_MASK 0x0380
#define E1000_SCR_MODE_AUTO 0x0180
Expand Down
33 changes: 19 additions & 14 deletions sys/dev/msk/if_msk.c
Expand Up @@ -1447,6 +1447,7 @@ msk_attach(device_t dev)
struct msk_softc *sc;
struct msk_if_softc *sc_if;
struct ifnet *ifp;
struct msk_mii_data *mmd;
int i, port, error;
uint8_t eaddr[6];

Expand All @@ -1456,7 +1457,8 @@ msk_attach(device_t dev)
error = 0;
sc_if = device_get_softc(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_port = port;
Expand Down Expand Up @@ -1602,7 +1604,8 @@ static int
mskc_attach(device_t dev)
{
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->msk_dev = dev;
Expand Down Expand Up @@ -1671,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_CLR);
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. */
sc->msk_num_port = 1;
if ((CSR_READ_1(sc, B2_Y2_HW_RES) & CFG_DUAL_MAC_MSK) ==
Expand Down Expand Up @@ -1814,15 +1813,18 @@ mskc_attach(device_t dev)
error = ENXIO;
goto fail;
}
port = malloc(sizeof(int), M_DEVBUF, M_WAITOK);
if (port == NULL) {
mmd = malloc(sizeof(struct msk_mii_data), M_DEVBUF, M_WAITOK | M_ZERO);
if (mmd == NULL) {
device_printf(dev, "failed to allocate memory for "
"ivars of PORT_A\n");
error = ENXIO;
goto fail;
}
*port = MSK_PORT_A;
device_set_ivars(sc->msk_devs[MSK_PORT_A], port);
mmd->port = MSK_PORT_A;
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) {
sc->msk_devs[MSK_PORT_B] = device_add_child(dev, "msk", -1);
Expand All @@ -1831,15 +1833,18 @@ mskc_attach(device_t dev)
error = ENXIO;
goto fail;
}
port = malloc(sizeof(int), M_DEVBUF, M_WAITOK);
if (port == NULL) {
mmd = malloc(sizeof(struct msk_mii_data), M_DEVBUF, M_WAITOK | M_ZERO);
if (mmd == NULL) {
device_printf(dev, "failed to allocate memory for "
"ivars of PORT_B\n");
error = ENXIO;
goto fail;
}
*port = MSK_PORT_B;
device_set_ivars(sc->msk_devs[MSK_PORT_B], port);
mmd->port = MSK_PORT_B;
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);
Expand Down
7 changes: 6 additions & 1 deletion sys/dev/msk/if_mskreg.h
Expand Up @@ -2404,6 +2404,12 @@ struct msk_ring_data {
#define MSK_TX_TIMEOUT 5
#define MSK_PUT_WM 10

struct msk_mii_data {
int port;
uint32_t pmd;
int mii_flags;
};

/* Forward decl. */
struct msk_if_softc;

Expand Down Expand Up @@ -2467,7 +2473,6 @@ struct msk_softc {
uint8_t msk_num_port;
int msk_ramsize; /* amount of SRAM on NIC */
uint32_t msk_pmd; /* physical media type */
uint32_t msk_coppertype;
uint32_t msk_intrmask;
uint32_t msk_intrhwemask;
uint32_t msk_pflags;
Expand Down

0 comments on commit 2ba2cfc

Please sign in to comment.