Date: Tue, 20 Jun 2017 18:11:24 +0000 (UTC) From: Luiz Otavio O Souza <loos@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r320157 - head/sys/dev/etherswitch/e6000sw Message-ID: <201706201811.v5KIBO8c064194@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: loos Date: Tue Jun 20 18:11:23 2017 New Revision: 320157 URL: https://svnweb.freebsd.org/changeset/base/320157 Log: Add support to 2.5G uplink for the MV88E6141 and MV88E6341 switches. Force the switch port settings for fixed media types. Tested with: 88E6176, 88E6141 Sponsored by: Rubicon Communications, LLC (Netgate) Modified: head/sys/dev/etherswitch/e6000sw/e6000sw.c head/sys/dev/etherswitch/e6000sw/e6000swreg.h Modified: head/sys/dev/etherswitch/e6000sw/e6000sw.c ============================================================================== --- head/sys/dev/etherswitch/e6000sw/e6000sw.c Tue Jun 20 17:39:24 2017 (r320156) +++ head/sys/dev/etherswitch/e6000sw/e6000sw.c Tue Jun 20 18:11:23 2017 (r320157) @@ -71,8 +71,10 @@ typedef struct e6000sw_softc { device_t miibus[E6000SW_MAX_PORTS]; struct proc *kproc; + uint32_t swid; uint32_t cpuports_mask; uint32_t fixed_mask; + uint32_t fixed25_mask; uint32_t ports_mask; int phy_base; int sw_addr; @@ -126,6 +128,7 @@ static int e6000sw_get_pvid(e6000sw_softc_t *, int, in static int e6000sw_set_pvid(e6000sw_softc_t *, int, int); static __inline bool e6000sw_is_cpuport(e6000sw_softc_t *, int); static __inline bool e6000sw_is_fixedport(e6000sw_softc_t *, int); +static __inline bool e6000sw_is_fixed25port(e6000sw_softc_t *, int); static __inline bool e6000sw_is_phyport(e6000sw_softc_t *, int); static __inline bool e6000sw_is_portenabled(e6000sw_softc_t *, int); static __inline struct mii_data *e6000sw_miiforphy(e6000sw_softc_t *, @@ -198,7 +201,6 @@ e6000sw_probe(device_t dev) e6000sw_softc_t *sc; const char *description; phandle_t dsa_node, switch_node; - uint32_t id; dsa_node = fdt_find_compatible(OF_finddevice("/"), "marvell,dsa", 0); @@ -223,35 +225,35 @@ e6000sw_probe(device_t dev) */ sx_init(&sc->sx, "e6000sw_tmp"); E6000SW_LOCK(sc); - id = e6000sw_readreg(sc, REG_PORT(0), SWITCH_ID); + sc->swid = e6000sw_readreg(sc, REG_PORT(0), SWITCH_ID) & 0xfff0; E6000SW_UNLOCK(sc); sx_destroy(&sc->sx); - switch (id & 0xfff0) { - case 0x3400: + switch (sc->swid) { + case MV88E6141: description = "Marvell 88E6141"; sc->phy_base = 0x10; sc->num_ports = 6; break; - case 0x3410: + case MV88E6341: description = "Marvell 88E6341"; sc->phy_base = 0x10; sc->num_ports = 6; break; - case 0x3520: + case MV88E6352: description = "Marvell 88E6352"; sc->num_ports = 7; break; - case 0x1720: + case MV88E6172: description = "Marvell 88E6172"; sc->num_ports = 7; break; - case 0x1760: + case MV88E6176: description = "Marvell 88E6176"; sc->num_ports = 7; break; default: - device_printf(dev, "Unrecognized device, id 0x%x.\n", id); + device_printf(dev, "Unrecognized device, id 0x%x.\n", sc->swid); return (ENXIO); } @@ -261,18 +263,22 @@ e6000sw_probe(device_t dev) } static int -e6000sw_parse_child_fdt(e6000sw_softc_t *sc, phandle_t child, - uint32_t *fixed_mask, uint32_t *cpu_mask, int *pport, int *pvlangroup) +e6000sw_parse_child_fdt(e6000sw_softc_t *sc, phandle_t child, int *pport, + int *pvlangroup) { - boolean_t fixed_link; - char portlabel[100]; + char *name, *portlabel; + int speed; + phandle_t fixed_link; uint32_t port, vlangroup; - if (fixed_mask == NULL || cpu_mask == NULL || pport == NULL) + if (pport == NULL || pvlangroup == NULL) return (ENXIO); - OF_getprop(child, "label", (void *)portlabel, sizeof(portlabel)); - OF_getencprop(child, "reg", (void *)&port, sizeof(port)); + if (OF_getencprop(child, "reg", (void *)&port, sizeof(port)) < 0) + return (ENXIO); + if (port >= sc->num_ports) + return (ENXIO); + *pport = port; if (OF_getencprop(child, "vlangroup", (void *)&vlangroup, sizeof(vlangroup)) > 0) { @@ -283,22 +289,36 @@ e6000sw_parse_child_fdt(e6000sw_softc_t *sc, phandle_t *pvlangroup = -1; } - if (port >= sc->num_ports) - return (ENXIO); - *pport = port; - - if (strncmp(portlabel, "cpu", 3) == 0) { - device_printf(sc->dev, "CPU port at %d\n", port); - *cpu_mask |= (1 << port); + if (OF_getprop_alloc(child, "label", 1, (void **)&portlabel) > 0) { + if (strncmp(portlabel, "cpu", 3) == 0) { + device_printf(sc->dev, "CPU port at %d\n", port); + sc->cpuports_mask |= (1 << port); + sc->fixed_mask |= (1 << port); + } + free(portlabel, M_OFWPROP); } fixed_link = OF_child(child); - if (fixed_link) { - *fixed_mask |= (1 << port); + if (fixed_link != 0 && + OF_getprop_alloc(fixed_link, "name", 1, (void **)&name) > 0) { + if (strncmp(name, "fixed-link", 10) == 0) { + /* Assume defaults: 1g - full-duplex. */ + sc->fixed_mask |= (1 << port); + if (OF_getencprop(fixed_link, "speed", &speed, + sizeof(speed)) > 0) { + if (speed == 2500 && + (MVSWITCH(sc, MV88E6141) || + MVSWITCH(sc, MV88E6341))) { + sc->fixed25_mask |= (1 << port); + } + } + } + free(name, M_OFWPROP); + } + if ((sc->fixed_mask & (1 << port)) != 0) device_printf(sc->dev, "fixed port at %d\n", port); - } else { + else device_printf(sc->dev, "PHY at port %d\n", port); - } return (0); } @@ -344,11 +364,12 @@ e6000sw_attach_miibus(e6000sw_softc_t *sc, int port) static int e6000sw_attach(device_t dev) { + etherswitch_vlangroup_t vg; e6000sw_softc_t *sc; phandle_t child; int err, port, vlangroup; int member_ports[E6000SW_NUM_VGROUPS]; - etherswitch_vlangroup_t vg; + uint32_t reg; err = 0; sc = device_get_softc(dev); @@ -365,8 +386,7 @@ e6000sw_attach(device_t dev) bzero(member_ports, sizeof(member_ports)); for (child = OF_child(sc->node); child != 0; child = OF_peer(child)) { - err = e6000sw_parse_child_fdt(sc, child, &sc->fixed_mask, - &sc->cpuports_mask, &port, &vlangroup); + err = e6000sw_parse_child_fdt(sc, child, &port, &vlangroup); if (err != 0) { device_printf(sc->dev, "failed to parse DTS\n"); goto out_fail; @@ -384,6 +404,30 @@ e6000sw_attach(device_t dev) goto out_fail; } + if (e6000sw_is_fixedport(sc, port)) { + /* Link must be down to change speed force value. */ + reg = e6000sw_readreg(sc, REG_PORT(port), PSC_CONTROL); + reg &= ~PSC_CONTROL_LINK_UP; + reg |= PSC_CONTROL_FORCED_LINK; + e6000sw_writereg(sc, REG_PORT(port), PSC_CONTROL, reg); + + /* + * Force speed, full-duplex, EEE off and flow-control + * on. + */ + if (e6000sw_is_fixed25port(sc, port)) + reg = PSC_CONTROL_SPD2500; + else + reg = PSC_CONTROL_SPD1000; + reg |= PSC_CONTROL_FORCED_DPX | PSC_CONTROL_FULLDPX | + PSC_CONTROL_FORCED_LINK | PSC_CONTROL_LINK_UP | + PSC_CONTROL_FORCED_FC | PSC_CONTROL_FC_ON | + PSC_CONTROL_FORCED_SPD; + if (MVSWITCH(sc, MV88E6141) || MVSWITCH(sc, MV88E6341)) + reg |= PSC_CONTROL_FORCED_EEE; + e6000sw_writereg(sc, REG_PORT(port), PSC_CONTROL, reg); + } + /* Don't attach miibus at CPU/fixed ports */ if (!e6000sw_is_phyport(sc, port)) continue; @@ -604,21 +648,19 @@ e6000sw_getport(device_t dev, etherswitch_port_t *p) E6000SW_LOCK(sc); e6000sw_get_pvid(sc, p->es_port, &p->es_pvid); - if (e6000sw_is_cpuport(sc, p->es_port)) { - p->es_flags |= ETHERSWITCH_PORT_CPU; + if (e6000sw_is_fixedport(sc, p->es_port)) { + if (e6000sw_is_cpuport(sc, p->es_port)) + p->es_flags |= ETHERSWITCH_PORT_CPU; ifmr = &p->es_ifmr; ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID; ifmr->ifm_count = 0; - ifmr->ifm_current = ifmr->ifm_active = - IFM_ETHER | IFM_1000_T | IFM_FDX; + if (e6000sw_is_fixed25port(sc, p->es_port)) + ifmr->ifm_active = IFM_2500_T; + else + ifmr->ifm_active = IFM_1000_T; + ifmr->ifm_active |= IFM_ETHER | IFM_FDX; + ifmr->ifm_current = ifmr->ifm_active; ifmr->ifm_mask = 0; - } else if (e6000sw_is_fixedport(sc, p->es_port)) { - ifmr = &p->es_ifmr; - ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID; - ifmr->ifm_count = 0; - ifmr->ifm_current = ifmr->ifm_active = - IFM_ETHER | IFM_1000_T | IFM_FDX; - ifmr->ifm_mask = 0; } else { mii = e6000sw_miiforphy(sc, p->es_port); err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr, @@ -648,8 +690,7 @@ e6000sw_setport(device_t dev, etherswitch_port_t *p) E6000SW_LOCK(sc); if (p->es_pvid != 0) e6000sw_set_pvid(sc, p->es_port, p->es_pvid); - if (!e6000sw_is_cpuport(sc, p->es_port) && - !e6000sw_is_fixedport(sc, p->es_port)) { + if (e6000sw_is_phyport(sc, p->es_port)) { mii = e6000sw_miiforphy(sc, p->es_port); err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr, &mii->mii_media, SIOCSIFMEDIA); @@ -964,6 +1005,13 @@ e6000sw_is_fixedport(e6000sw_softc_t *sc, int port) { return ((sc->fixed_mask & (1 << port)) ? true : false); +} + +static __inline bool +e6000sw_is_fixed25port(e6000sw_softc_t *sc, int port) +{ + + return ((sc->fixed25_mask & (1 << port)) ? true : false); } static __inline bool Modified: head/sys/dev/etherswitch/e6000sw/e6000swreg.h ============================================================================== --- head/sys/dev/etherswitch/e6000sw/e6000swreg.h Tue Jun 20 17:39:24 2017 (r320156) +++ head/sys/dev/etherswitch/e6000sw/e6000swreg.h Tue Jun 20 18:11:23 2017 (r320157) @@ -42,6 +42,15 @@ struct atu_opt { * Definitions for the Marvell 88E6000 series Ethernet Switch. */ +/* Switch IDs. */ +#define MV88E6141 0x3400 +#define MV88E6341 0x3410 +#define MV88E6352 0x3520 +#define MV88E6172 0x1720 +#define MV88E6176 0x1760 + +#define MVSWITCH(_sc, id) ((_sc)->swid == (id)) + /* * Switch Registers */ @@ -64,6 +73,17 @@ struct atu_opt { #define PORT_STATUS_PHY_DETECT_MASK (1 << 12) #define PSC_CONTROL 0x1 +#define PSC_CONTROL_FORCED_SPD (1 << 13) +#define PSC_CONTROL_EEE_ON (1 << 9) +#define PSC_CONTROL_FORCED_EEE (1 << 8) +#define PSC_CONTROL_FC_ON (1 << 7) +#define PSC_CONTROL_FORCED_FC (1 << 6) +#define PSC_CONTROL_LINK_UP (1 << 5) +#define PSC_CONTROL_FORCED_LINK (1 << 4) +#define PSC_CONTROL_FULLDPX (1 << 3) +#define PSC_CONTROL_FORCED_DPX (1 << 2) +#define PSC_CONTROL_SPD2500 0x3 +#define PSC_CONTROL_SPD1000 0x2 #define SWITCH_ID 0x3 #define PORT_CONTROL 0x4 #define PORT_CONTROL_1 0x5
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201706201811.v5KIBO8c064194>