diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2020-11-29 13:00:24 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2020-11-29 13:00:24 +0000 |
commit | 0f76b4922994be1cfa5e43a5927ebb2ae9a816d2 (patch) | |
tree | c15efa4729d2cc7c1f3f9832a3a70208adb418db | |
parent | 1c76ab191b8c5e15a1c77be60f636a3d75ab1802 (diff) |
Add support for 1000base-x and 2500base-x connections.
ok patrick@
-rw-r--r-- | sys/dev/fdt/if_mvneta.c | 100 | ||||
-rw-r--r-- | sys/dev/fdt/if_mvnetareg.h | 6 |
2 files changed, 98 insertions, 8 deletions
diff --git a/sys/dev/fdt/if_mvneta.c b/sys/dev/fdt/if_mvneta.c index 0e9d542c321..ee0920bbf35 100644 --- a/sys/dev/fdt/if_mvneta.c +++ b/sys/dev/fdt/if_mvneta.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_mvneta.c,v 1.13 2020/07/10 13:26:36 patrick Exp $ */ +/* $OpenBSD: if_mvneta.c,v 1.14 2020/11/29 13:00:23 kettenis Exp $ */ /* $NetBSD: if_mvneta.c,v 1.41 2015/04/15 10:15:40 hsuenaga Exp $ */ /* * Copyright (c) 2007, 2008, 2013 KIYOHARA Takashi @@ -41,6 +41,7 @@ #include <sys/mbuf.h> #include <machine/bus.h> +#include <machine/cpufunc.h> #include <machine/fdt.h> #include <dev/ofw/openfirm.h> @@ -159,6 +160,8 @@ struct mvneta_softc { PHY_MODE_SGMII, PHY_MODE_RGMII, PHY_MODE_RGMII_ID, + PHY_MODE_1000BASEX, + PHY_MODE_2500BASEX, } sc_phy_mode; int sc_fixed_link; int sc_inband_status; @@ -166,6 +169,7 @@ struct mvneta_softc { int sc_phyloc; int sc_link; int sc_sfp; + int sc_node; }; @@ -268,6 +272,7 @@ mvneta_miibus_statchg(struct device *self) void mvneta_inband_statchg(struct mvneta_softc *sc) { + uint64_t subtype = IFM_SUBTYPE(sc->sc_mii.mii_media_active); uint32_t reg; sc->sc_mii.mii_media_status = IFM_AVALID; @@ -276,7 +281,11 @@ mvneta_inband_statchg(struct mvneta_softc *sc) reg = MVNETA_READ(sc, MVNETA_PS0); if (reg & MVNETA_PS0_LINKUP) sc->sc_mii.mii_media_status |= IFM_ACTIVE; - if (reg & MVNETA_PS0_GMIISPEED) + if (sc->sc_phy_mode == PHY_MODE_2500BASEX) + sc->sc_mii.mii_media_active |= subtype; + else if (sc->sc_phy_mode == PHY_MODE_1000BASEX) + sc->sc_mii.mii_media_active |= subtype; + else if (reg & MVNETA_PS0_GMIISPEED) sc->sc_mii.mii_media_active |= IFM_1000_T; else if (reg & MVNETA_PS0_MIISPEED) sc->sc_mii.mii_media_active |= IFM_100_TX; @@ -344,6 +353,64 @@ mvneta_wininit(struct mvneta_softc *sc) MVNETA_WRITE(sc, MVNETA_BARE, en); } +#define COMPHY_SIP_POWER_ON 0x82000001 +#define COMPHY_SIP_POWER_OFF 0x82000002 +#define COMPHY_SPEED(x) ((x) << 2) +#define COMPHY_SPEED_1_25G 0 /* SGMII 1G */ +#define COMPHY_SPEED_2_5G 1 +#define COMPHY_SPEED_3_125G 2 /* SGMII 2.5G */ +#define COMPHY_SPEED_5G 3 +#define COMPHY_SPEED_5_15625G 4 /* XFI 5G */ +#define COMPHY_SPEED_6G 5 +#define COMPHY_SPEED_10_3125G 6 /* XFI 10G */ +#define COMPHY_UNIT(x) ((x) << 8) +#define COMPHY_MODE(x) ((x) << 12) +#define COMPHY_MODE_SATA 1 +#define COMPHY_MODE_SGMII 2 /* SGMII 1G */ +#define COMPHY_MODE_HS_SGMII 3 /* SGMII 2.5G */ +#define COMPHY_MODE_USB3H 4 +#define COMPHY_MODE_USB3D 5 +#define COMPHY_MODE_PCIE 6 +#define COMPHY_MODE_RXAUI 7 +#define COMPHY_MODE_XFI 8 +#define COMPHY_MODE_SFI 9 +#define COMPHY_MODE_USB3 10 + +void +mvneta_comphy_init(struct mvneta_softc *sc) +{ + int node, phys[2], lane, unit; + uint32_t mode; + + if (OF_getpropintarray(sc->sc_node, "phys", phys, sizeof(phys)) != + sizeof(phys)) + return; + node = OF_getnodebyphandle(phys[0]); + if (!node) + return; + + lane = OF_getpropint(node, "reg", 0); + unit = phys[1]; + + switch (sc->sc_phy_mode) { + case PHY_MODE_1000BASEX: + case PHY_MODE_SGMII: + mode = COMPHY_MODE(COMPHY_MODE_SGMII) | + COMPHY_SPEED(COMPHY_SPEED_1_25G) | + COMPHY_UNIT(unit); + break; + case PHY_MODE_2500BASEX: + mode = COMPHY_MODE(COMPHY_MODE_HS_SGMII) | + COMPHY_SPEED(COMPHY_SPEED_3_125G) | + COMPHY_UNIT(unit); + break; + default: + return; + } + + smc_call(COMPHY_SIP_POWER_ON, lane, mode, 0); +} + int mvneta_match(struct device *parent, void *cfdata, void *aux) { @@ -358,7 +425,7 @@ mvneta_attach(struct device *parent, struct device *self, void *aux) { struct mvneta_softc *sc = (struct mvneta_softc *) self; struct fdt_attach_args *faa = aux; - uint32_t ctl0, ctl2, panc; + uint32_t ctl0, ctl2, ctl4, panc; struct ifnet *ifp; int i, len, node; char *phy_mode; @@ -374,6 +441,7 @@ mvneta_attach(struct device *parent, struct device *self, void *aux) return; } sc->sc_dmat = faa->fa_dmat; + sc->sc_node = faa->fa_node; clock_enable(faa->fa_node, NULL); @@ -395,6 +463,10 @@ mvneta_attach(struct device *parent, struct device *self, void *aux) sc->sc_phy_mode = PHY_MODE_RGMII_ID; else if (!strncmp(phy_mode, "rgmii", strlen("rgmii"))) sc->sc_phy_mode = PHY_MODE_RGMII; + else if (!strncmp(phy_mode, "1000base-x", strlen("1000base-x"))) + sc->sc_phy_mode = PHY_MODE_1000BASEX; + else if (!strncmp(phy_mode, "2500base-x", strlen("2500base-x"))) + sc->sc_phy_mode = PHY_MODE_2500BASEX; else { printf("%s: cannot use phy-mode %s\n", self->dv_xname, phy_mode); @@ -532,6 +604,7 @@ mvneta_attach(struct device *parent, struct device *self, void *aux) /* Setup phy. */ ctl0 = MVNETA_READ(sc, MVNETA_PMACC0); ctl2 = MVNETA_READ(sc, MVNETA_PMACC2); + ctl4 = MVNETA_READ(sc, MVNETA_PMACC4); panc = MVNETA_READ(sc, MVNETA_PANC); /* Force link down to change in-band settings. */ @@ -539,8 +612,11 @@ mvneta_attach(struct device *parent, struct device *self, void *aux) panc |= MVNETA_PANC_FORCELINKFAIL; MVNETA_WRITE(sc, MVNETA_PANC, panc); + mvneta_comphy_init(sc); + ctl0 &= ~MVNETA_PMACC0_PORTTYPE; ctl2 &= ~(MVNETA_PMACC2_PORTMACRESET | MVNETA_PMACC2_INBANDAN); + ctl4 &= ~(MVNETA_PMACC4_SHORT_PREAMBLE); panc &= ~(MVNETA_PANC_INBANDANEN | MVNETA_PANC_INBANDRESTARTAN | MVNETA_PANC_SETMIISPEED | MVNETA_PANC_SETGMIISPEED | MVNETA_PANC_ANSPEEDEN | MVNETA_PANC_SETFCEN | @@ -559,6 +635,17 @@ mvneta_attach(struct device *parent, struct device *self, void *aux) MVNETA_SERDESCFG_SGMII_PROTO); ctl2 |= MVNETA_PMACC2_PCSEN; break; + case PHY_MODE_1000BASEX: + MVNETA_WRITE(sc, MVNETA_SERDESCFG, + MVNETA_SERDESCFG_SGMII_PROTO); + ctl2 |= MVNETA_PMACC2_PCSEN; + break; + case PHY_MODE_2500BASEX: + MVNETA_WRITE(sc, MVNETA_SERDESCFG, + MVNETA_SERDESCFG_HSGMII_PROTO); + ctl2 |= MVNETA_PMACC2_PCSEN; + ctl4 |= MVNETA_PMACC4_SHORT_PREAMBLE; + break; default: break; } @@ -590,6 +677,7 @@ mvneta_attach(struct device *parent, struct device *self, void *aux) MVNETA_WRITE(sc, MVNETA_PMACC0, ctl0); MVNETA_WRITE(sc, MVNETA_PMACC2, ctl2); + MVNETA_WRITE(sc, MVNETA_PMACC4, ctl4); MVNETA_WRITE(sc, MVNETA_PANC, panc); /* Port reset */ @@ -661,10 +749,8 @@ mvneta_attach_deferred(struct device *self) } else ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO); } else { - ifmedia_add(&sc->sc_mii.mii_media, - IFM_ETHER|IFM_MANUAL, 0, NULL); - ifmedia_set(&sc->sc_mii.mii_media, - IFM_ETHER|IFM_MANUAL); + ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO, 0, NULL); + ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO); if (sc->sc_inband_status) { mvneta_inband_statchg(sc); diff --git a/sys/dev/fdt/if_mvnetareg.h b/sys/dev/fdt/if_mvnetareg.h index cd851c64bbe..4de18660c6e 100644 --- a/sys/dev/fdt/if_mvnetareg.h +++ b/sys/dev/fdt/if_mvnetareg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_mvnetareg.h,v 1.1 2017/08/25 20:09:34 patrick Exp $ */ +/* $OpenBSD: if_mvnetareg.h,v 1.2 2020/11/29 13:00:23 kettenis Exp $ */ /* $NetBSD: mvnetareg.h,v 1.8 2013/12/23 02:23:25 kiyohara Exp $ */ /* * Copyright (c) 2007, 2013 KIYOHARA Takashi @@ -464,6 +464,7 @@ /* Port Serdes Config (MVNETA_SERDESCFG) */ #define MVNETA_SERDESCFG_SGMII_PROTO 0x0cc7 #define MVNETA_SERDESCFG_QSGMII_PROTO 0x0667 +#define MVNETA_SERDESCFG_HSGMII_PROTO 0x1107 /* Ether Type Priority (MVNETA_ETP) */ #define MVNETA_ETP_ETHERTYPEPRIEN (1 << 0) /* EtherType Prio Ena */ @@ -627,6 +628,9 @@ /* Port MAC Control 3 (MVNETA_PMACC3) */ #define MVNETA_PMACC3_IPG_MASK 0x7f80 +/* Port MAC Control 4 (MVNETA_PMACC4) */ +#define MVNETA_PMACC4_SHORT_PREAMBLE (1 << 1) + /* Port Interrupt Cause/Mask (MVNETA_PIC_2/MVNETA_PIM_2) */ #define MVNETA_PI_2_INTSUM (1 << 0) #define MVNETA_PI_2_LSC (1 << 1) /* LinkStatus Change */ |