From: Visa Hankala Subject: Re: sys/cnmac: support CN71xx 1000BASE-X ports To: "Kirill A. Korinsky" Cc: tech@openbsd.org Date: Wed, 22 Apr 2026 15:02:25 +0000 On Wed, Apr 22, 2026 at 01:13:26AM +0200, Kirill A. Korinsky wrote: > On Tue, 21 Apr 2026 18:09:59 +0200, > Visa Hankala wrote: > > > > > + for (child = OF_child(node); child != 0; child = OF_peer(child)) { > > > + if (!OF_is_compatible(child, "cavium,octeon-3860-pip-port")) > > > + continue; > > > + reg = OF_getpropint(child, "reg", -1); > > > + if (reg < 0 || reg >= nitems(sc->sc_port_types)) > > > + continue; > > > + > > > + sc->sc_port_types[reg] = GMX_SGMII_PORT; > > > > If I read this correctly, this uses SGMII mode regardless of the > > actual port mode. I think this port type setting should be conditional > > to the cavium,sgmii-mac-1000x-mode property. > > > > However, does the INF_MODE logic give an incorrect result with your > > hardware? > > > > I've tried: > > if (0 && cn30xxgmx_init_cn71xx(sc) == 0) > break; > > and no, it doesn't work. It picks interface@4/ethernet@0 as cnmac0 and it > doesn't work. > > Actually I not sure that to do with interface@1/ethernet@0 which has > sgmii-mac-phy-mode and no phy in DTS. > > But uboot reports that: > > PCIe: Port 0 link active, 1 lanes, speed gen2 > PCIe: Link timeout on port 1, probably the slot is empty > PCIe: Port 2 not in PCIe mode, skipping > Net: octeth0 > Interface 0 has 1 ports (SGMII) > > which is interface@0/ethernet@0 whith sgmii-mac-1000x-mode. > > > > @@ -1382,6 +1444,8 @@ cn30xxgmx_sgmii_speed(struct cn30xxgmx_p > > > > > > misc_ctl = PCS_READ_8(sc, PCS_MISC_CTL); > > > CLR(misc_ctl, PCS_MISC_CTL_SAMP_PT); > > > + if (sc->sc_port_disable_an) > > > + SET(misc_ctl, PCS_MISC_CTL_AN_OVRD); > > > > I wonder if this should set (or clear) the PCS_MISC_CTL_MODE bit if > > the SGMII MAC mode is enabled (or not). Would this help with the > > hardware initialization during boot? > > > > I have checked Linux and FreeBSD-13, and they both do not toggle > PCS_MISC_CTL_MODE to switch between SGMII MAC mode and 1000BASE-X. > > I had played with that and interface@1/ethernet@0, but can't figure out how > to make it works, so, for now I'd like to have minimal diff which is > attached and address your remakrs, and which allows to initialize cnmac0 > which somehow works if the switch was initialized in uboot via dhcp. Indeed, making the switch functional is a separate thing. Some detective work is needed if the device tree does not indicate how the switch control interface is connected to the OCTEON SoC. OK visa@ > Index: sys/arch/octeon/dev/cn30xxgmx.c > =================================================================== > RCS file: /home/cvs/src/sys/arch/octeon/dev/cn30xxgmx.c,v > diff -u -p -r1.55 cn30xxgmx.c > --- sys/arch/octeon/dev/cn30xxgmx.c 8 Jul 2024 08:07:45 -0000 1.55 > +++ sys/arch/octeon/dev/cn30xxgmx.c 21 Apr 2026 22:28:32 -0000 > @@ -169,22 +169,64 @@ cn30xxgmx_match(struct device *parent, v > } > > int > -cn30xxgmx_get_phy_phandle(int interface, int port) > +cn30xxgmx_get_phy_phandle(int interface, int port, int *port_1000x, > + int *disable_an) > { > char name[64]; > int node; > int phandle = 0; > > + if (port_1000x != NULL) > + *port_1000x = 0; > + if (disable_an != NULL) > + *disable_an = 0; > + > snprintf(name, sizeof(name), > "/soc/pip@11800a0000000/interface@%x/ethernet@%x", > interface, port); > node = OF_finddevice(name); > - if (node != - 1) > + if (node != -1) { > phandle = OF_getpropint(node, "phy-handle", 0); > + if (port_1000x != NULL) { > + *port_1000x = OF_getproplen(node, > + "cavium,sgmii-mac-1000x-mode") >= 0; > + } > + if (disable_an != NULL) { > + *disable_an = OF_getproplen(node, > + "cavium,disable-autonegotiation") >= 0; > + } > + } > return phandle; > } > > void > +cn30xxgmx_init_cn71xx(struct cn30xxgmx_softc *sc) > +{ > + char name[64]; > + int child, node, reg; > + > + snprintf(name, sizeof(name), > + "/soc/pip@11800a0000000/interface@%x", sc->sc_unitno); > + node = OF_finddevice(name); > + if (node == -1) > + return; > + > + for (child = OF_child(node); child != 0; child = OF_peer(child)) { > + if (!OF_is_compatible(child, "cavium,octeon-3860-pip-port")) > + continue; > + if (OF_getproplen(child, "cavium,sgmii-mac-1000x-mode") < 0) > + continue; > + reg = OF_getpropint(child, "reg", -1); > + if (reg < 0 || reg >= nitems(sc->sc_port_types)) > + continue; > + > + sc->sc_port_types[reg] = GMX_SGMII_PORT; > + if (sc->sc_nports < reg + 1) > + sc->sc_nports = reg + 1; > + } > +} > + > +void > cn30xxgmx_attach(struct device *parent, struct device *self, void *aux) > { > struct cn30xxgmx_attach_args gmx_aa; > @@ -193,6 +235,7 @@ cn30xxgmx_attach(struct device *parent, > struct cn30xxgmx_softc *sc = (void *)self; > struct cn30xxsmi_softc *smi; > int i; > + int phandle; > int phy_addr; > int port; > int status; > @@ -224,15 +267,20 @@ cn30xxgmx_attach(struct device *parent, > printf("\n"); > > for (i = 0; i < sc->sc_nports; i++) { > + port_sc = &sc->sc_ports[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)) > + phandle = cn30xxgmx_get_phy_phandle(sc->sc_unitno, i, > + &port_sc->sc_port_1000x, > + &port_sc->sc_port_disable_an); > + smi = NULL; > + phy_addr = -1; > + if (!(port_sc->sc_port_1000x && phandle == 0) && > + cn30xxsmi_get_phy(phandle, port, &smi, &phy_addr)) > continue; > > - port_sc = &sc->sc_ports[i]; > port_sc->sc_port_gmx = sc; > port_sc->sc_port_no = port; > port_sc->sc_port_type = sc->sc_port_types[i]; > @@ -421,6 +469,10 @@ cn30xxgmx_init(struct cn30xxgmx_softc *s > break; > } > > + cn30xxgmx_init_cn71xx(sc); > + if (sc->sc_nports != 0) > + break; > + > inf_mode = bus_space_read_8(sc->sc_regt, sc->sc_regh, > GMX0_INF_MODE); > if ((inf_mode & INF_MODE_EN) == 0) > @@ -1341,6 +1393,17 @@ cn30xxgmx_sgmii_enable(struct cn30xxgmx_ > return 1; > } > > + if (sc->sc_port_disable_an) { > + CLR(ctl_reg, PCS_MR_CONTROL_AN_EN); > + CLR(ctl_reg, PCS_MR_CONTROL_RST_AN); > + CLR(ctl_reg, PCS_MR_CONTROL_PWR_DN); > + CLR(ctl_reg, PCS_MR_CONTROL_SPDLSB); > + SET(ctl_reg, PCS_MR_CONTROL_SPDMSB); > + SET(ctl_reg, PCS_MR_CONTROL_DUPLEX); > + PCS_WRITE_8(sc, PCS_MR_CONTROL, ctl_reg); > + return 0; > + } > + > /* Start a new SGMII autonegotiation. */ > SET(ctl_reg, PCS_MR_CONTROL_AN_EN); > SET(ctl_reg, PCS_MR_CONTROL_RST_AN); > @@ -1382,6 +1445,8 @@ cn30xxgmx_sgmii_speed(struct cn30xxgmx_p > > misc_ctl = PCS_READ_8(sc, PCS_MISC_CTL); > CLR(misc_ctl, PCS_MISC_CTL_SAMP_PT); > + if (sc->sc_port_disable_an) > + SET(misc_ctl, PCS_MISC_CTL_AN_OVRD); > > /* Disable the GMX port if the link is down. */ > if (cn30xxgmx_link_status(sc)) > Index: sys/arch/octeon/dev/cn30xxgmxvar.h > =================================================================== > RCS file: /home/cvs/src/sys/arch/octeon/dev/cn30xxgmxvar.h,v > diff -u -p -r1.14 cn30xxgmxvar.h > --- sys/arch/octeon/dev/cn30xxgmxvar.h 20 May 2024 23:13:33 -0000 1.14 > +++ sys/arch/octeon/dev/cn30xxgmxvar.h 21 Apr 2026 21:16:43 -0000 > @@ -61,6 +61,8 @@ struct cn30xxgmx_port_softc { > bus_space_handle_t sc_port_regh; > int sc_port_no; /* GMX0:0, GMX0:1, ... */ > int sc_port_type; > + int sc_port_1000x; > + int sc_port_disable_an; > uint64_t sc_link; > struct mii_data *sc_port_mii; > struct arpcom *sc_port_ac; > Index: sys/arch/octeon/dev/if_cnmac.c > =================================================================== > RCS file: /home/cvs/src/sys/arch/octeon/dev/if_cnmac.c,v > diff -u -p -r1.87 if_cnmac.c > --- sys/arch/octeon/dev/if_cnmac.c 21 Apr 2026 20:20:09 -0000 1.87 > +++ sys/arch/octeon/dev/if_cnmac.c 21 Apr 2026 22:23:05 -0000 > @@ -482,6 +482,19 @@ cnmac_mediainit(struct cnmac_softc *sc) > ifmedia_init(&sc->sc_mii.mii_media, 0, cnmac_mediachange, > cnmac_mediastatus); > > + if (sc->sc_gmx_port->sc_port_1000x) { > + ifmedia_add(&sc->sc_mii.mii_media, > + IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL); > + ifmedia_set(&sc->sc_mii.mii_media, > + IFM_ETHER | IFM_1000_T | IFM_FDX); > + sc->sc_mii.mii_media_status = IFM_AVALID | IFM_ACTIVE; > + sc->sc_mii.mii_media_active = > + IFM_ETHER | IFM_1000_T | IFM_FDX; > + ifp->if_baudrate = IF_Gbps(1); > + ifp->if_link_state = LINK_STATE_FULL_DUPLEX; > + return 0; > + } > + > mii_attach(&sc->sc_dev, &sc->sc_mii, > 0xffffffff, sc->sc_phy_addr, MII_OFFSET_ANY, MIIF_DOPAUSE); > > @@ -503,6 +516,14 @@ cnmac_mediastatus(struct ifnet *ifp, str > { > struct cnmac_softc *sc = ifp->if_softc; > > + if (sc->sc_gmx_port->sc_port_1000x) { > + ifmr->ifm_status = sc->sc_mii.mii_media_status; > + ifmr->ifm_active = (sc->sc_mii.mii_media_active & > + ~IFM_ETH_FMASK) | > + sc->sc_gmx_port->sc_port_flowflags; > + return; > + } > + > mii_pollstat(&sc->sc_mii); > ifmr->ifm_status = sc->sc_mii.mii_media_status; > ifmr->ifm_active = sc->sc_mii.mii_media_active; > @@ -514,6 +535,9 @@ int > cnmac_mediachange(struct ifnet *ifp) > { > struct cnmac_softc *sc = ifp->if_softc; > + > + if (sc->sc_gmx_port->sc_port_1000x) > + return 0; > > if ((ifp->if_flags & IFF_UP) == 0) > return 0; > > > -- > wbr, Kirill