summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2020-11-29 13:00:24 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2020-11-29 13:00:24 +0000
commit0f76b4922994be1cfa5e43a5927ebb2ae9a816d2 (patch)
treec15efa4729d2cc7c1f3f9832a3a70208adb418db
parent1c76ab191b8c5e15a1c77be60f636a3d75ab1802 (diff)
Add support for 1000base-x and 2500base-x connections.
ok patrick@
-rw-r--r--sys/dev/fdt/if_mvneta.c100
-rw-r--r--sys/dev/fdt/if_mvnetareg.h6
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 */