summaryrefslogtreecommitdiff
path: root/sys/arch/octeon
diff options
context:
space:
mode:
authorVisa Hankala <visa@cvs.openbsd.org>2020-09-08 13:54:49 +0000
committerVisa Hankala <visa@cvs.openbsd.org>2020-09-08 13:54:49 +0000
commit071416ea9253d28cdc56b5a258cf0e9a7dd24924 (patch)
treebf81be538d8eea03fe8c7e2999cb1b435377c045 /sys/arch/octeon
parenta085c5058af6a0a272eacef9e9a45380c90ce4df (diff)
Handle AGL interface
This makes certain machines' management network port usable.
Diffstat (limited to 'sys/arch/octeon')
-rw-r--r--sys/arch/octeon/dev/cn30xxgmx.c285
-rw-r--r--sys/arch/octeon/dev/cn30xxgmxreg.h51
-rw-r--r--sys/arch/octeon/dev/cn30xxgmxvar.h3
-rw-r--r--sys/arch/octeon/dev/cn30xxpko.c21
-rw-r--r--sys/arch/octeon/dev/cn30xxpkoreg.h12
-rw-r--r--sys/arch/octeon/dev/octpip.c13
6 files changed, 366 insertions, 19 deletions
diff --git a/sys/arch/octeon/dev/cn30xxgmx.c b/sys/arch/octeon/dev/cn30xxgmx.c
index 3ff9d6b848b..7f99ff48e8a 100644
--- a/sys/arch/octeon/dev/cn30xxgmx.c
+++ b/sys/arch/octeon/dev/cn30xxgmx.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cn30xxgmx.c,v 1.45 2020/09/04 15:18:05 visa Exp $ */
+/* $OpenBSD: cn30xxgmx.c,v 1.46 2020/09/08 13:54:48 visa Exp $ */
/*
* Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -73,6 +73,19 @@
#define _GMX_PORT_WR8(sc, off, v) \
bus_space_write_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_regh, (off), (v))
+#define AGL_GMX_RD8(sc, reg) \
+ bus_space_read_8((sc)->sc_port_gmx->sc_regt, \
+ (sc)->sc_port_gmx->sc_regh, (reg))
+#define AGL_GMX_WR8(sc, reg, val) \
+ bus_space_write_8((sc)->sc_port_gmx->sc_regt, \
+ (sc)->sc_port_gmx->sc_regh, (reg), (val))
+#define AGL_GMX_PORT_RD8(sc, reg) \
+ bus_space_read_8((sc)->sc_port_gmx->sc_regt, \
+ (sc)->sc_port_regh, (reg))
+#define AGL_GMX_PORT_WR8(sc, reg, val) \
+ bus_space_write_8((sc)->sc_port_gmx->sc_regt, \
+ (sc)->sc_port_regh, (reg), (val))
+
#define PCS_READ_8(sc, reg) \
bus_space_read_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_pcs_regh, \
(reg))
@@ -93,6 +106,10 @@ int cn30xxgmx_port_phy_addr(int);
int cn30xxgmx_init(struct cn30xxgmx_softc *);
int cn30xxgmx_rx_frm_ctl_xable(struct cn30xxgmx_port_softc *,
uint64_t, int);
+void cn30xxgmx_agl_init(struct cn30xxgmx_port_softc *);
+int cn30xxgmx_agl_enable(struct cn30xxgmx_port_softc *, int);
+int cn30xxgmx_agl_speed(struct cn30xxgmx_port_softc *);
+int cn30xxgmx_agl_timing(struct cn30xxgmx_port_softc *);
int cn30xxgmx_rgmii_enable(struct cn30xxgmx_port_softc *, int);
int cn30xxgmx_rgmii_speed(struct cn30xxgmx_port_softc *);
int cn30xxgmx_rgmii_speed_newlink(struct cn30xxgmx_port_softc *,
@@ -115,6 +132,12 @@ static const int cn30xxgmx_rx_adr_cam_regs[] = {
GMX0_RX0_ADR_CAM3, GMX0_RX0_ADR_CAM4, GMX0_RX0_ADR_CAM5
};
+struct cn30xxgmx_port_ops cn30xxgmx_port_ops_agl = {
+ .port_ops_enable = cn30xxgmx_agl_enable,
+ .port_ops_speed = cn30xxgmx_agl_speed,
+ .port_ops_timing = cn30xxgmx_agl_timing,
+};
+
struct cn30xxgmx_port_ops cn30xxgmx_port_ops_mii = {
/* XXX not implemented */
};
@@ -146,7 +169,8 @@ struct cn30xxgmx_port_ops *cn30xxgmx_port_ops[] = {
[GMX_GMII_PORT] = &cn30xxgmx_port_ops_gmii,
[GMX_RGMII_PORT] = &cn30xxgmx_port_ops_rgmii,
[GMX_SGMII_PORT] = &cn30xxgmx_port_ops_sgmii,
- [GMX_SPI42_PORT] = &cn30xxgmx_port_ops_spi42
+ [GMX_SPI42_PORT] = &cn30xxgmx_port_ops_spi42,
+ [GMX_AGL_PORT] = &cn30xxgmx_port_ops_agl,
};
struct cfattach octgmx_ca = {sizeof(struct cn30xxgmx_softc),
@@ -214,7 +238,10 @@ cn30xxgmx_attach(struct device *parent, struct device *self, void *aux)
}
for (i = 0; i < sc->sc_nports; i++) {
- port = GMX_PORT_NUM(sc->sc_unitno, i);
+ if (sc->sc_port_types[i] == GMX_AGL_PORT)
+ port = 24;
+ else
+ port = GMX_PORT_NUM(sc->sc_unitno, i);
if (cn30xxsmi_get_phy(cn30xxgmx_get_phy_phandle(sc->sc_unitno,
i), port, &smi, &phy_addr))
continue;
@@ -231,6 +258,10 @@ cn30xxgmx_attach(struct device *parent, struct device *self, void *aux)
panic(": can't map port register");
switch (port_sc->sc_port_type) {
+ case GMX_AGL_PORT:
+ cn30xxgmx_agl_init(port_sc);
+ break;
+
case GMX_MII_PORT:
case GMX_GMII_PORT:
case GMX_RGMII_PORT: {
@@ -273,6 +304,7 @@ cn30xxgmx_print(void *aux, const char *pnp)
{
struct cn30xxgmx_attach_args *ga = aux;
static const char *types[] = {
+ [GMX_AGL_PORT] = "AGL",
[GMX_MII_PORT] = "MII",
[GMX_GMII_PORT] = "GMII",
[GMX_RGMII_PORT] = "RGMII",
@@ -284,7 +316,7 @@ cn30xxgmx_print(void *aux, const char *pnp)
printf("%s at %s", ga->ga_name, pnp);
#endif
- printf(": %s", types[ga->ga_port_type]);
+ printf(": port %d %s", ga->ga_portno, types[ga->ga_port_type]);
return UNCONF;
}
@@ -296,17 +328,19 @@ cn30xxgmx_init(struct cn30xxgmx_softc *sc)
uint64_t inf_mode;
int i, id;
- inf_mode = bus_space_read_8(sc->sc_regt, sc->sc_regh, GMX0_INF_MODE);
- if ((inf_mode & INF_MODE_EN) == 0) {
- printf("ports are disabled\n");
- sc->sc_nports = 0;
- return 1;
- }
-
id = octeon_get_chipid();
switch (octeon_model_family(id)) {
case OCTEON_MODEL_FAMILY_CN31XX:
+ inf_mode = bus_space_read_8(sc->sc_regt, sc->sc_regh,
+ GMX0_INF_MODE);
+ if ((inf_mode & INF_MODE_EN) == 0) {
+ printf("ports are disabled\n");
+ sc->sc_nports = 0;
+ result = 1;
+ break;
+ }
+
/*
* CN31XX-HM-1.01
* 14.1 Packet Interface Introduction
@@ -329,6 +363,15 @@ cn30xxgmx_init(struct cn30xxgmx_softc *sc)
break;
case OCTEON_MODEL_FAMILY_CN30XX:
case OCTEON_MODEL_FAMILY_CN50XX:
+ inf_mode = bus_space_read_8(sc->sc_regt, sc->sc_regh,
+ GMX0_INF_MODE);
+ if ((inf_mode & INF_MODE_EN) == 0) {
+ printf("ports are disabled\n");
+ sc->sc_nports = 0;
+ result = 1;
+ break;
+ }
+
/*
* CN30XX-HM-1.0
* 13.1 Packet Interface Introduction
@@ -359,6 +402,15 @@ cn30xxgmx_init(struct cn30xxgmx_softc *sc)
case OCTEON_MODEL_FAMILY_CN61XX: {
uint64_t qlm_cfg;
+ inf_mode = bus_space_read_8(sc->sc_regt, sc->sc_regh,
+ GMX0_INF_MODE);
+ if ((inf_mode & INF_MODE_EN) == 0) {
+ printf("ports are disabled\n");
+ sc->sc_nports = 0;
+ result = 1;
+ break;
+ }
+
if (sc->sc_unitno == 0)
qlm_cfg = octeon_xkphys_read_8(MIO_QLM_CFG(2));
else
@@ -379,6 +431,32 @@ cn30xxgmx_init(struct cn30xxgmx_softc *sc)
break;
}
case OCTEON_MODEL_FAMILY_CN71XX:
+ if (sc->sc_unitno == 4) {
+ uint64_t val;
+
+ sc->sc_nports = 0;
+
+ val = bus_space_read_8(sc->sc_regt, sc->sc_regh,
+ AGL_PRT_CTL(0));
+ if ((val & AGL_PRT_CTL_MODE_M) ==
+ AGL_PRT_CTL_MODE_RGMII) {
+ sc->sc_nports = 1;
+ sc->sc_port_types[0] = GMX_AGL_PORT;
+ }
+ if (sc->sc_nports == 0)
+ result = 1;
+ break;
+ }
+
+ inf_mode = bus_space_read_8(sc->sc_regt, sc->sc_regh,
+ GMX0_INF_MODE);
+ if ((inf_mode & INF_MODE_EN) == 0) {
+ printf("ports are disabled\n");
+ sc->sc_nports = 0;
+ result = 1;
+ break;
+ }
+
switch (inf_mode & INF_MODE_MODE) {
case INF_MODE_MODE_SGMII:
sc->sc_nports = 4;
@@ -755,6 +833,191 @@ cn30xxgmx_reset_flowctl(struct cn30xxgmx_port_softc *sc)
return 0;
}
+void
+cn30xxgmx_agl_init(struct cn30xxgmx_port_softc *sc)
+{
+ uint64_t val;
+ int port = 0;
+
+ /* Disable link for initialization. */
+ val = AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
+ CLR(val, AGL_GMX_PRT_CFG_EN);
+ AGL_GMX_PORT_WR8(sc, AGL_GMX_PRT_CFG, val);
+ (void)AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
+
+ val = AGL_GMX_RD8(sc, AGL_PRT_CTL(port));
+ CLR(val, AGL_PRT_CTL_CLKRST);
+ CLR(val, AGL_PRT_CTL_DLLRST);
+ CLR(val, AGL_PRT_CTL_CLKTX_BYP);
+ CLR(val, AGL_PRT_CTL_CLKTX_SET_M);
+ CLR(val, AGL_PRT_CTL_CLKRX_BYP);
+ CLR(val, AGL_PRT_CTL_CLKRX_SET_M);
+ CLR(val, AGL_PRT_CTL_REFCLK_SEL_M);
+ AGL_GMX_WR8(sc, AGL_PRT_CTL(port), val);
+ (void)AGL_GMX_RD8(sc, AGL_PRT_CTL(port));
+
+ /* Let the DLL settle. */
+ delay(5);
+
+ val = AGL_GMX_RD8(sc, AGL_PRT_CTL(port));
+ CLR(val, AGL_PRT_CTL_DRV_BYP);
+ AGL_GMX_WR8(sc, AGL_PRT_CTL(port), val);
+ (void)AGL_GMX_RD8(sc, AGL_PRT_CTL(port));
+
+ val = AGL_GMX_RD8(sc, AGL_PRT_CTL(port));
+ SET(val, AGL_PRT_CTL_COMP);
+ AGL_GMX_WR8(sc, AGL_PRT_CTL(port), val);
+ (void)AGL_GMX_RD8(sc, AGL_PRT_CTL(port));
+
+ /* Let the compensation controller settle. */
+ delay(20);
+
+ val = AGL_GMX_RX_FRM_CTL_PRE_ALIGN
+ | AGL_GMX_RX_FRM_CTL_PAD_LEN
+ | AGL_GMX_RX_FRM_CTL_VLAN_LEN
+ | AGL_GMX_RX_FRM_CTL_PRE_FREE
+ | AGL_GMX_RX_FRM_CTL_MCST
+ | AGL_GMX_RX_FRM_CTL_BCK
+ | AGL_GMX_RX_FRM_CTL_DRP
+ | AGL_GMX_RX_FRM_CTL_PRE_STRP
+ | AGL_GMX_RX_FRM_CTL_PRE_CHK;
+ AGL_GMX_PORT_WR8(sc, AGL_GMX_RX_FRM_CTL, val);
+ (void)AGL_GMX_PORT_RD8(sc, AGL_GMX_RX_FRM_CTL);
+}
+
+void
+cn30xxgmx_agl_up(struct cn30xxgmx_port_softc *sc)
+{
+ uint64_t val;
+
+ val = AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
+ SET(val, AGL_GMX_PRT_CFG_RX_EN);
+ SET(val, AGL_GMX_PRT_CFG_TX_EN);
+ AGL_GMX_PORT_WR8(sc, AGL_GMX_PRT_CFG, val);
+
+ val = AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
+ SET(val, AGL_GMX_PRT_CFG_EN);
+ AGL_GMX_PORT_WR8(sc, AGL_GMX_PRT_CFG, val);
+ (void)AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
+}
+
+void
+cn30xxgmx_agl_down(struct cn30xxgmx_port_softc *sc)
+{
+ uint64_t val;
+ int timeout;
+
+ val = AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
+ CLR(val, AGL_GMX_PRT_CFG_EN);
+ AGL_GMX_PORT_WR8(sc, AGL_GMX_PRT_CFG, val);
+
+ val = AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
+ CLR(val, AGL_GMX_PRT_CFG_RX_EN);
+ CLR(val, AGL_GMX_PRT_CFG_TX_EN);
+ AGL_GMX_PORT_WR8(sc, AGL_GMX_PRT_CFG, val);
+ (void)AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
+
+ /* Wait until the port is idle. */
+ for (timeout = 1000; timeout > 0; timeout--) {
+ const uint64_t idlemask = AGL_GMX_PRT_CFG_RX_IDLE |
+ AGL_GMX_PRT_CFG_TX_IDLE;
+ val = AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
+ if ((val & idlemask) == idlemask)
+ break;
+ delay(1000);
+ }
+}
+
+int
+cn30xxgmx_agl_enable(struct cn30xxgmx_port_softc *sc, int enable)
+{
+ if (enable)
+ cn30xxgmx_agl_up(sc);
+ else
+ cn30xxgmx_agl_down(sc);
+ return 0;
+}
+
+int
+cn30xxgmx_agl_speed(struct cn30xxgmx_port_softc *sc)
+{
+ struct ifnet *ifp = &sc->sc_port_ac->ac_if;
+ uint64_t clk_cnt, prt_cfg, val;
+ unsigned int maxlen;
+ int port = 0;
+
+ cn30xxgmx_agl_down(sc);
+
+ prt_cfg = AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
+
+ if (ISSET(sc->sc_port_mii->mii_media_active, IFM_FDX))
+ SET(prt_cfg, AGL_GMX_PRT_CFG_DUPLEX);
+ else
+ CLR(prt_cfg, AGL_GMX_PRT_CFG_DUPLEX);
+
+ switch (ifp->if_baudrate) {
+ case IF_Mbps(10):
+ CLR(prt_cfg, AGL_GMX_PRT_CFG_SPEED);
+ SET(prt_cfg, AGL_GMX_PRT_CFG_SPEED_MSB);
+ CLR(prt_cfg, AGL_GMX_PRT_CFG_SLOTTIME);
+ SET(prt_cfg, AGL_GMX_PRT_CFG_BURST);
+ clk_cnt = 50;
+ break;
+ case IF_Mbps(100):
+ CLR(prt_cfg, AGL_GMX_PRT_CFG_SPEED);
+ CLR(prt_cfg, AGL_GMX_PRT_CFG_SPEED_MSB);
+ CLR(prt_cfg, AGL_GMX_PRT_CFG_SLOTTIME);
+ SET(prt_cfg, AGL_GMX_PRT_CFG_BURST);
+ clk_cnt = 5;
+ break;
+ case IF_Gbps(1):
+ default:
+ SET(prt_cfg, AGL_GMX_PRT_CFG_SPEED);
+ CLR(prt_cfg, AGL_GMX_PRT_CFG_SPEED_MSB);
+ SET(prt_cfg, AGL_GMX_PRT_CFG_SLOTTIME);
+ if (ISSET(sc->sc_port_mii->mii_media_active, IFM_FDX))
+ SET(prt_cfg, AGL_GMX_PRT_CFG_BURST);
+ else
+ CLR(prt_cfg, AGL_GMX_PRT_CFG_BURST);
+ clk_cnt = 1;
+ break;
+ }
+
+ AGL_GMX_PORT_WR8(sc, AGL_GMX_PRT_CFG, prt_cfg);
+ (void)AGL_GMX_PORT_RD8(sc, AGL_GMX_PRT_CFG);
+
+ val = AGL_GMX_PORT_RD8(sc, AGL_GMX_TX_CLK);
+ CLR(val, AGL_GMX_TX_CLK_CLK_CNT_M);
+ SET(val, clk_cnt << AGL_GMX_TX_CLK_CLK_CNT_S);
+ AGL_GMX_PORT_WR8(sc, AGL_GMX_TX_CLK, val);
+ (void)AGL_GMX_PORT_RD8(sc, AGL_GMX_TX_CLK);
+
+ maxlen = roundup(ifp->if_hardmtu + ETHER_HDR_LEN + ETHER_CRC_LEN +
+ ETHER_VLAN_ENCAP_LEN, 8);
+ AGL_GMX_PORT_WR8(sc, AGL_GMX_RX_JABBER, maxlen);
+ AGL_GMX_PORT_WR8(sc, AGL_GMX_RX_FRM_MAX, maxlen);
+ (void)AGL_GMX_PORT_RD8(sc, AGL_GMX_RX_FRM_MAX);
+
+ cn30xxgmx_agl_up(sc);
+
+ val = AGL_GMX_RD8(sc, AGL_PRT_CTL(port));
+ SET(val, AGL_PRT_CTL_CLKRST);
+ AGL_GMX_WR8(sc, AGL_PRT_CTL(port), val);
+
+ val = AGL_GMX_RD8(sc, AGL_PRT_CTL(port));
+ SET(val, AGL_PRT_CTL_ENABLE);
+ AGL_GMX_WR8(sc, AGL_PRT_CTL(port), val);
+ (void)AGL_GMX_RD8(sc, AGL_PRT_CTL(port));
+
+ return 0;
+}
+
+int
+cn30xxgmx_agl_timing(struct cn30xxgmx_port_softc *sc)
+{
+ return 0;
+}
+
int
cn30xxgmx_rgmii_enable(struct cn30xxgmx_port_softc *sc, int enable)
{
diff --git a/sys/arch/octeon/dev/cn30xxgmxreg.h b/sys/arch/octeon/dev/cn30xxgmxreg.h
index 037c6ab4ba4..c601a40aba9 100644
--- a/sys/arch/octeon/dev/cn30xxgmxreg.h
+++ b/sys/arch/octeon/dev/cn30xxgmxreg.h
@@ -3,7 +3,7 @@
* DONT EDIT THIS FILE
*/
-/* $OpenBSD: cn30xxgmxreg.h,v 1.6 2017/04/08 10:53:48 visa Exp $ */
+/* $OpenBSD: cn30xxgmxreg.h,v 1.7 2020/09/08 13:54:48 visa Exp $ */
/*
* Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -655,6 +655,55 @@
#define GMX0_BASE_IF0 0x0001180008000000ULL
#define GMX0_BASE_IF_SIZE(n) (GMX0_BASE_PORT_SIZE * (n))
+#define AGL_BASE 0x00011800e0000000ULL
+#define AGL_SIZE 0x4000
+
+#define AGL_GMX_PRT_CFG 0x0010
+#define AGL_GMX_PRT_CFG_TX_IDLE 0x0000000000002000ULL
+#define AGL_GMX_PRT_CFG_RX_IDLE 0x0000000000001000ULL
+#define AGL_GMX_PRT_CFG_SPEED_MSB 0x0000000000000100ULL
+#define AGL_GMX_PRT_CFG_BURST 0x0000000000000040ULL
+#define AGL_GMX_PRT_CFG_TX_EN 0x0000000000000020ULL
+#define AGL_GMX_PRT_CFG_RX_EN 0x0000000000000010ULL
+#define AGL_GMX_PRT_CFG_SLOTTIME 0x0000000000000008ULL
+#define AGL_GMX_PRT_CFG_DUPLEX 0x0000000000000004ULL
+#define AGL_GMX_PRT_CFG_SPEED 0x0000000000000002ULL
+#define AGL_GMX_PRT_CFG_EN 0x0000000000000001ULL
+
+#define AGL_GMX_RX_FRM_CTL 0x0018
+#define AGL_GMX_RX_FRM_CTL_PRE_ALIGN 0x0000000000000200ULL
+#define AGL_GMX_RX_FRM_CTL_PAD_LEN 0x0000000000000100ULL
+#define AGL_GMX_RX_FRM_CTL_VLAN_LEN 0x0000000000000080ULL
+#define AGL_GMX_RX_FRM_CTL_PRE_FREE 0x0000000000000040ULL
+#define AGL_GMX_RX_FRM_CTL_SMAC 0x0000000000000020ULL
+#define AGL_GMX_RX_FRM_CTL_MCST 0x0000000000000010ULL
+#define AGL_GMX_RX_FRM_CTL_BCK 0x0000000000000008ULL
+#define AGL_GMX_RX_FRM_CTL_DRP 0x0000000000000004ULL
+#define AGL_GMX_RX_FRM_CTL_PRE_STRP 0x0000000000000002ULL
+#define AGL_GMX_RX_FRM_CTL_PRE_CHK 0x0000000000000001ULL
+
+#define AGL_GMX_RX_FRM_MAX 0x0030
+#define AGL_GMX_RX_JABBER 0x0038
+
+#define AGL_GMX_TX_CLK 0x0208
+#define AGL_GMX_TX_CLK_CLK_CNT_M 0x000000000000003fULL
+#define AGL_GMX_TX_CLK_CLK_CNT_S 0
+
+#define AGL_PRT_CTL(i) (0x2000 + (i) * 8)
+#define AGL_PRT_CTL_DRV_BYP 0x8000000000000000ULL
+#define AGL_PRT_CTL_CLK_SET_M 0x000000007f000000ULL
+#define AGL_PRT_CTL_CLKRX_BYP 0x0000000000800000ULL
+#define AGL_PRT_CTL_CLKRX_SET_M 0x00000000007f0000ULL
+#define AGL_PRT_CTL_CLKTX_BYP 0x0000000000008000ULL
+#define AGL_PRT_CTL_CLKTX_SET_M 0x0000000000007f00ULL
+#define AGL_PRT_CTL_REFCLK_SEL_M 0x00000000000000c0ULL
+#define AGL_PRT_CTL_DLLRST 0x0000000000000010ULL
+#define AGL_PRT_CTL_COMP 0x0000000000000008ULL
+#define AGL_PRT_CTL_ENABLE 0x0000000000000004ULL
+#define AGL_PRT_CTL_CLKRST 0x0000000000000002ULL
+#define AGL_PRT_CTL_MODE_M 0x0000000000000001ULL
+#define AGL_PRT_CTL_MODE_RGMII 0x0000000000000000ULL
+
/* -------------------------------------------------------------------------- */
/* Low-level SGMII link control */
diff --git a/sys/arch/octeon/dev/cn30xxgmxvar.h b/sys/arch/octeon/dev/cn30xxgmxvar.h
index a0e0cabab7e..066ba8b2347 100644
--- a/sys/arch/octeon/dev/cn30xxgmxvar.h
+++ b/sys/arch/octeon/dev/cn30xxgmxvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cn30xxgmxvar.h,v 1.10 2020/09/04 15:18:05 visa Exp $ */
+/* $OpenBSD: cn30xxgmxvar.h,v 1.11 2020/09/08 13:54:48 visa Exp $ */
/*
* Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -45,6 +45,7 @@
#define GMX_RGMII_PORT 3
#define GMX_SGMII_PORT 4
#define GMX_SPI42_PORT 5
+#define GMX_AGL_PORT 6
#define GMX_FRM_MAX_SIZ 0x600
diff --git a/sys/arch/octeon/dev/cn30xxpko.c b/sys/arch/octeon/dev/cn30xxpko.c
index 569eb056466..2ea636b5711 100644
--- a/sys/arch/octeon/dev/cn30xxpko.c
+++ b/sys/arch/octeon/dev/cn30xxpko.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cn30xxpko.c,v 1.6 2017/11/05 04:57:28 visa Exp $ */
+/* $OpenBSD: cn30xxpko.c,v 1.7 2020/09/08 13:54:48 visa Exp $ */
/*
* Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -140,7 +140,8 @@ int
cn30xxpko_port_config(struct cn30xxpko_softc *sc)
{
paddr_t buf_ptr = 0;
- uint64_t mem_queue_ptrs;
+ uint64_t mem_queue_ptrs, val;
+ int i;
KASSERT(sc->sc_port < 32);
@@ -150,6 +151,22 @@ cn30xxpko_port_config(struct cn30xxpko_softc *sc)
KASSERT(buf_ptr != 0);
+ if (sc->sc_port == 24) {
+ /* Set up PKO for AGL port. */
+ _PKO_WR8(sc, PKO_REG_READ_IDX_OFFSET, 1ULL << 8);
+ for (i = 0; i < 40; i++) {
+ val = _PKO_RD8(sc, PKO_MEM_PORT_PTRS_OFFSET);
+ if ((val & PKO_MEM_PORT_PTRS_PID_M) == 24) {
+ CLR(val, PKO_MEM_PORT_PTRS_EID_M);
+ SET(val, 10ULL << PKO_MEM_PORT_PTRS_EID_S);
+ CLR(val, PKO_MEM_PORT_PTRS_BP_PORT_M);
+ SET(val, 40ULL << PKO_MEM_PORT_PTRS_BP_PORT_S);
+ _PKO_WR8(sc, PKO_MEM_PORT_PTRS_OFFSET, val);
+ break;
+ }
+ }
+ }
+
/* assume one queue maped one port */
mem_queue_ptrs = 0;
SET(mem_queue_ptrs, PKO_MEM_QUEUE_PTRS_TAIL);
diff --git a/sys/arch/octeon/dev/cn30xxpkoreg.h b/sys/arch/octeon/dev/cn30xxpkoreg.h
index 9f8436364cc..4eae27924b0 100644
--- a/sys/arch/octeon/dev/cn30xxpkoreg.h
+++ b/sys/arch/octeon/dev/cn30xxpkoreg.h
@@ -3,7 +3,7 @@
* DONT EDIT THIS FILE
*/
-/* $OpenBSD: cn30xxpkoreg.h,v 1.1 2011/06/16 11:22:30 syuu Exp $ */
+/* $OpenBSD: cn30xxpkoreg.h,v 1.2 2020/09/08 13:54:48 visa Exp $ */
/*
* Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -83,6 +83,7 @@
#define PKO_REG_DEBUG0_OFFSET 0x00098ULL
#define PKO_MEM_QUEUE_PTRS_OFFSET 0x01000ULL
#define PKO_MEM_QUEUE_QOS_OFFSET 0x01008ULL
+#define PKO_MEM_PORT_PTRS_OFFSET 0x01010ULL
#define PKO_MEM_COUNT0_OFFSET 0x01080ULL
#define PKO_MEM_COUNT1_OFFSET 0x01088ULL
#define PKO_MEM_DEBUG0_OFFSET 0x01100ULL
@@ -198,6 +199,15 @@
#define PKO_MEM_QUEUE_QOS_QID 0x000000000000007fULL
/*
+ * PKO_MEM_PORT_PTRS
+ */
+#define PKO_MEM_PORT_PTRS_BP_PORT_M 0x000000000000fc00ULL
+#define PKO_MEM_PORT_PTRS_BP_PORT_S 10
+#define PKO_MEM_PORT_PTRS_EID_M 0x00000000000003c0ULL
+#define PKO_MEM_PORT_PTRS_EID_S 6
+#define PKO_MEM_PORT_PTRS_PID_M 0x000000000000003fULL
+
+/*
* PKO_MEM_COUNT0
*/
#define PKO_MEM_COUNT0_63_32 0xffffffff00000000ULL
diff --git a/sys/arch/octeon/dev/octpip.c b/sys/arch/octeon/dev/octpip.c
index e078eba506a..dd476df412d 100644
--- a/sys/arch/octeon/dev/octpip.c
+++ b/sys/arch/octeon/dev/octpip.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: octpip.c,v 1.2 2019/09/28 22:20:25 deraadt Exp $ */
+/* $OpenBSD: octpip.c,v 1.3 2020/09/08 13:54:48 visa Exp $ */
/*
* Copyright (c) 2019 Visa Hankala
@@ -57,6 +57,7 @@ octpip_attach(struct device *parent, struct device *self, void *aux)
{
struct iobus_attach_args iaa;
struct fdt_attach_args *faa = aux;
+ paddr_t addr;
uint32_t ifindex;
int node;
@@ -65,14 +66,20 @@ octpip_attach(struct device *parent, struct device *self, void *aux)
for (node = OF_child(faa->fa_node); node != 0; node = OF_peer(node)) {
if (!OF_is_compatible(node, "cavium,octeon-3860-pip-interface"))
continue;
+
ifindex = OF_getpropint(node, "reg", (uint32_t)-1);
- if (ifindex >= 16)
+ if (ifindex < 2)
+ addr = GMX0_BASE_PORT0 + GMX_BLOCK_SIZE * ifindex;
+ else if (ifindex == 4)
+ addr = AGL_BASE;
+ else
continue;
+
memset(&iaa, 0, sizeof(iaa));
iaa.aa_name = "octgmx";
iaa.aa_bust = faa->fa_iot;
iaa.aa_dmat = faa->fa_dmat;
- iaa.aa_addr = GMX0_BASE_PORT0 + GMX_BLOCK_SIZE * ifindex;
+ iaa.aa_addr = addr;
iaa.aa_irq = -1;
iaa.aa_unitno = ifindex;
config_found(self, &iaa, octpip_print);