diff --git a/sys/dev/sk/if_sk.c b/sys/dev/sk/if_sk.c index 8a5dbf2ac9f3..0f70832bf4e2 100644 --- a/sys/dev/sk/if_sk.c +++ b/sys/dev/sk/if_sk.c @@ -159,6 +159,21 @@ static struct sk_type sk_devs[] = { DEVICEID_SK_V2, "Marvell Gigabit Ethernet" }, + { + VENDORID_MARVELL, + DEVICEID_MRVL_4360, + "Marvell 88E8052 Gigabit Ethernet Controller" + }, + { + VENDORID_MARVELL, + DEVICEID_MRVL_4361, + "Marvell 88E8050 Gigabit Ethernet Controller" + }, + { + VENDORID_MARVELL, + DEVICEID_MRVL_4362, + "Marvell 88E8053 Gigabit Ethernet Controller" + }, { VENDORID_MARVELL, DEVICEID_BELKIN_5005, @@ -571,6 +586,7 @@ sk_miibus_readreg(dev, phy, reg) case SK_YUKON: case SK_YUKON_LITE: case SK_YUKON_LP: + case SK_YUKON_EC: v = sk_marv_miibus_readreg(sc_if, phy, reg); break; default: @@ -600,6 +616,7 @@ sk_miibus_writereg(dev, phy, reg, val) case SK_YUKON: case SK_YUKON_LITE: case SK_YUKON_LP: + case SK_YUKON_EC: v = sk_marv_miibus_writereg(sc_if, phy, reg, val); break; default: @@ -627,6 +644,7 @@ sk_miibus_statchg(dev) case SK_YUKON: case SK_YUKON_LITE: case SK_YUKON_LP: + case SK_YUKON_EC: sk_marv_miibus_statchg(sc_if); break; } @@ -852,6 +870,7 @@ sk_setmulti(sc_if) case SK_YUKON: case SK_YUKON_LITE: case SK_YUKON_LP: + case SK_YUKON_EC: SK_YU_WRITE_2(sc_if, YUKON_MCAH1, 0); SK_YU_WRITE_2(sc_if, YUKON_MCAH2, 0); SK_YU_WRITE_2(sc_if, YUKON_MCAH3, 0); @@ -893,6 +912,7 @@ sk_setmulti(sc_if) case SK_YUKON: case SK_YUKON_LITE: case SK_YUKON_LP: + case SK_YUKON_EC: bcopy(LLADDR( (struct sockaddr_dl *)ifma->ifma_addr), maddr, ETHER_ADDR_LEN); @@ -917,6 +937,7 @@ sk_setmulti(sc_if) case SK_YUKON: case SK_YUKON_LITE: case SK_YUKON_LP: + case SK_YUKON_EC: SK_YU_WRITE_2(sc_if, YUKON_MCAH1, hashes[0] & 0xffff); SK_YU_WRITE_2(sc_if, YUKON_MCAH2, (hashes[0] >> 16) & 0xffff); SK_YU_WRITE_2(sc_if, YUKON_MCAH3, hashes[1] & 0xffff); @@ -947,6 +968,7 @@ sk_setpromisc(sc_if) case SK_YUKON: case SK_YUKON_LITE: case SK_YUKON_LP: + case SK_YUKON_EC: if (ifp->if_flags & IFF_PROMISC) { SK_YU_CLRBIT_2(sc_if, YUKON_RCR, YU_RCR_UFLEN | YU_RCR_MUFLEN); @@ -1395,6 +1417,9 @@ sk_reset(sc) case SK_GENESIS: sc->sk_int_ticks = SK_IMTIMER_TICKS_GENESIS; break; + case SK_YUKON_EC: + sc->sk_int_ticks = SK_IMTIMER_TICKS_YUKON_EC; + break; default: sc->sk_int_ticks = SK_IMTIMER_TICKS_YUKON; break; @@ -1432,6 +1457,7 @@ sk_probe(dev) case SK_YUKON: case SK_YUKON_LITE: case SK_YUKON_LP: + case SK_YUKON_EC: device_set_desc(dev, "Marvell Semiconductor, Inc. Yukon"); break; } @@ -1527,8 +1553,12 @@ sk_attach(dev) * receiver and b) between the two XMACs, if this is a * dual port NIC. Our algotithm is to divide up the memory * evenly so that everyone gets a fair share. + * + * Just to be contrary, Yukon2 appears to have separate memory + * for each MAC. */ - if (sk_win_read_1(sc, SK_CONFIG) & SK_CONFIG_SINGLEMAC) { + if (SK_IS_YUKON2(sc) || + sk_win_read_1(sc, SK_CONFIG) & SK_CONFIG_SINGLEMAC) { u_int32_t chunk, val; chunk = sc->sk_ramsize / 2; @@ -1555,22 +1585,32 @@ sk_attach(dev) /* Read and save PHY type and set PHY address */ sc_if->sk_phytype = sk_win_read_1(sc, SK_EPROM1) & 0xF; - switch(sc_if->sk_phytype) { - case SK_PHYTYPE_XMAC: - sc_if->sk_phyaddr = SK_PHYADDR_XMAC; - break; - case SK_PHYTYPE_BCOM: - sc_if->sk_phyaddr = SK_PHYADDR_BCOM; - break; - case SK_PHYTYPE_MARV_COPPER: + if (!SK_YUKON_FAMILY(sc->sk_type)) { + switch(sc_if->sk_phytype) { + case SK_PHYTYPE_XMAC: + sc_if->sk_phyaddr = SK_PHYADDR_XMAC; + break; + case SK_PHYTYPE_BCOM: + sc_if->sk_phyaddr = SK_PHYADDR_BCOM; + break; + default: + device_printf(sc->sk_dev, "unsupported PHY type: %d\n", + sc_if->sk_phytype); + error = ENODEV; + SK_IF_UNLOCK(sc_if); + goto fail; + } + } else { + if (sc_if->sk_phytype < SK_PHYTYPE_MARV_COPPER && + sc->sk_pmd == IFM_1000_T) { + /* not initialized, punt */ + sc_if->sk_phytype = SK_PHYTYPE_MARV_COPPER; + } + sc_if->sk_phyaddr = SK_PHYADDR_MARV; - break; - default: - device_printf(sc->sk_dev, "unsupported PHY type: %d\n", - sc_if->sk_phytype); - error = ENODEV; - SK_IF_UNLOCK(sc_if); - goto fail; + + if (sc->sk_pmd != IFM_1000_T && sc->sk_pmd != IFM_1000_CX) + sc_if->sk_phytype = SK_PHYTYPE_MARV_FIBER; } /* @@ -1605,6 +1645,7 @@ sk_attach(dev) case SK_YUKON: case SK_YUKON_LITE: case SK_YUKON_LP: + case SK_YUKON_EC: sk_init_yukon(sc_if); break; } @@ -1637,7 +1678,7 @@ skc_attach(dev) device_t dev; { struct sk_softc *sc; - int error = 0, rid, *port; + int error = 0, rid, *port, sk_macs; uint8_t skrs; char *pname, *revstr; @@ -1759,6 +1800,12 @@ skc_attach(dev) sc->sk_pmd = IFM_1000_T; break; default: + if (SK_YUKON_FAMILY(sc->sk_type) && (sk_win_read_1(sc, SK_EPROM1) + & 0xF) < SK_PHYTYPE_MARV_COPPER) { + /* not initialized, punt */ + sc->sk_pmd = IFM_1000_T; + break; + } device_printf(dev, "unknown media type: 0x%x\n", sk_win_read_1(sc, SK_PMDTYPE)); error = ENXIO; @@ -1777,6 +1824,9 @@ skc_attach(dev) pname = sc->sk_vpd_prodname; break; case DEVICEID_SK_V2: + case DEVICEID_MRVL_4360: + case DEVICEID_MRVL_4361: + case DEVICEID_MRVL_4362: /* YUKON VPD PN might bear no resemblance to reality. */ switch (sc->sk_type) { case SK_GENESIS: @@ -1792,6 +1842,9 @@ skc_attach(dev) case SK_YUKON_LP: pname = "Marvell Yukon LP Gigabit Ethernet"; break; + case SK_YUKON_EC: + pname = "Marvell Yukon-2 EC Gigabit Ethernet"; + break; default: pname = "Marvell Yukon (Unknown) Gigabit Ethernet"; break; @@ -1841,6 +1894,21 @@ skc_attach(dev) revstr = ""; break; } + } else if (sc->sk_type == SK_YUKON_EC) { + switch (sc->sk_rev) { + case SK_YUKON_EC_REV_A1: + revstr = "A1"; + break; + case SK_YUKON_EC_REV_A2: + revstr = "A2"; + break; + case SK_YUKON_EC_REV_A3: + revstr = "A3"; + break; + default: + revstr = ""; + break; + } } else { revstr = ""; } @@ -1899,7 +1967,23 @@ skc_attach(dev) *port = SK_PORT_A; device_set_ivars(sc->sk_devs[SK_PORT_A], port); - if (!(sk_win_read_1(sc, SK_CONFIG) & SK_CONFIG_SINGLEMAC)) { + sk_macs = 1; + + if (SK_IS_YUKON2(sc)) { + u_int8_t hw; + + hw = sk_win_read_1(sc, SK_Y2_HWRES); + if ((hw & SK_Y2_HWRES_LINK_MASK) == SK_Y2_HWRES_LINK_DUAL) { + if ((sk_win_read_1(sc, SK_Y2_CLKGATE) & + SK_Y2_CLKGATE_LINK2_INACTIVE) == 0) + sk_macs++; + } + } else { + if (!(sk_win_read_1(sc, SK_CONFIG) & SK_CONFIG_SINGLEMAC)) + sk_macs++; + } + + if (sk_macs > 1) { sc->sk_devs[SK_PORT_B] = device_add_child(dev, "sk", -1); if (sc->sk_devs[SK_PORT_B] == NULL) { device_printf(dev, "failed to add child for PORT_B\n"); @@ -3813,6 +3897,7 @@ sk_init_locked(sc_if) case SK_YUKON: case SK_YUKON_LITE: case SK_YUKON_LP: + case SK_YUKON_EC: sk_init_yukon(sc_if); break; } @@ -3916,6 +4001,7 @@ sk_init_locked(sc_if) case SK_YUKON: case SK_YUKON_LITE: case SK_YUKON_LP: + case SK_YUKON_EC: reg = SK_YU_READ_2(sc_if, YUKON_GPCR); reg |= YU_GPCR_TXEN | YU_GPCR_RXEN; #if 0 @@ -3937,6 +4023,7 @@ sk_init_locked(sc_if) case SK_YUKON: case SK_YUKON_LITE: case SK_YUKON_LP: + case SK_YUKON_EC: callout_reset(&sc_if->sk_tick_ch, hz, sk_yukon_tick, sc_if); break; } @@ -4010,6 +4097,7 @@ sk_stop(sc_if) case SK_YUKON: case SK_YUKON_LITE: case SK_YUKON_LP: + case SK_YUKON_EC: SK_IF_WRITE_1(sc_if,0, SK_RXMF1_CTRL_TEST, SK_RFCTL_RESET_SET); SK_IF_WRITE_1(sc_if,0, SK_TXMF1_CTRL_TEST, SK_TFCTL_RESET_SET); break; diff --git a/sys/dev/sk/if_skreg.h b/sys/dev/sk/if_skreg.h index 8b1952352760..507f93aa3e66 100644 --- a/sys/dev/sk/if_skreg.h +++ b/sys/dev/sk/if_skreg.h @@ -55,13 +55,23 @@ #define SK_YUKON 0xB0 #define SK_YUKON_LITE 0xB1 #define SK_YUKON_LP 0xB2 +#define SK_YUKON_XL 0xB3 +#define SK_YUKON_EC_U 0xB4 +#define SK_YUKON_EC 0xB6 +#define SK_YUKON_FE 0xB7 #define SK_YUKON_FAMILY(x) ((x) & 0xB0) +#define SK_IS_YUKON2(sc) \ + ((sc)->sk_type >= SK_YUKON_XL && (sc)->sk_type <= SK_YUKON_FE) /* Known revisions in SK_CONFIG. */ #define SK_YUKON_LITE_REV_A0 0x0 /* invented, see test in skc_attach. */ #define SK_YUKON_LITE_REV_A1 0x3 #define SK_YUKON_LITE_REV_A3 0x7 +#define SK_YUKON_EC_REV_A1 0x0 +#define SK_YUKON_EC_REV_A2 0x1 +#define SK_YUKON_EC_REV_A3 0x2 + /* * SysKonnect PCI vendor ID */ @@ -78,6 +88,13 @@ #define DEVICEID_SK_V1 0x4300 #define DEVICEID_SK_V2 0x4320 +/* + * Marvell gigabit ethernet device IDs + */ +#define DEVICEID_MRVL_4360 0x4360 +#define DEVICEID_MRVL_4361 0x4361 +#define DEVICEID_MRVL_4362 0x4362 + /* * Belkin F5D5005 */ @@ -345,8 +362,10 @@ #define SK_CONFIG 0x011A #define SK_CHIPVER 0x011B #define SK_EPROM0 0x011C -#define SK_EPROM1 0x011D -#define SK_EPROM2 0x011E +#define SK_EPROM1 0x011D /* yukon/genesis */ +#define SK_Y2_CLKGATE 0x011D /* yukon 2 */ +#define SK_EPROM2 0x011E /* yukon/genesis */ +#define SK_Y2_HWRES 0x011E /* yukon 2 */ #define SK_EPROM3 0x011F #define SK_EP_ADDR 0x0120 #define SK_EP_DATA 0x0124 @@ -452,6 +471,13 @@ #define SK_GPIO_DIR8 0x01000000 #define SK_GPIO_DIR9 0x02000000 +#define SK_Y2_CLKGATE_LINK2_INACTIVE 0x80 /* port 2 inactive */ + +#define SK_Y2_HWRES_LINK_1 0x01 +#define SK_Y2_HWRES_LINK_2 0x02 +#define SK_Y2_HWRES_LINK_MASK (SK_Y2_HWRES_LINK_1 | SK_Y2_HWRES_LINK_2) +#define SK_Y2_HWRES_LINK_DUAL (SK_Y2_HWRES_LINK_1 | SK_Y2_HWRES_LINK_2) + /* Block 3 Ram interface and MAC arbiter registers */ #define SK_RAMADDR 0x0180 #define SK_RAMDATA0 0x0184