using fdt. This lets the system utilize multiple MDIO controllers.
This patch enables all RJ45 Ethernet ports on EdgeRouter Pro.
The SFP module slots do not work yet.
OK kettenis@, jmatthew@
-# $OpenBSD: GENERIC,v 1.30 2016/12/21 13:59:57 visa Exp $
+# $OpenBSD: GENERIC,v 1.31 2017/05/02 13:26:49 visa Exp $
#
# For further information on compiling OpenBSD kernels, see the config(8)
# man page.
ppb* at pci? # PCI-PCI bridges
pci* at ppb?
+cn30xxsmi* at fdt? # MDIO controller
octmmc* at fdt? # MMC host controller
sdmmc* at octmmc? # SD/MMC bus
-# $OpenBSD: RAMDISK,v 1.28 2016/12/21 13:59:57 visa Exp $
+# $OpenBSD: RAMDISK,v 1.29 2017/05/02 13:26:49 visa Exp $
machine octeon mips64
maxusers 4
ppb* at pci?
pci* at ppb?
+cn30xxsmi* at fdt? # MDIO controller
octmmc* at fdt? # MMC host controller
sdmmc* at octmmc? # SD/MMC bus
-# $OpenBSD: files.octeon,v 1.34 2017/04/24 13:54:28 visa Exp $
+# $OpenBSD: files.octeon,v 1.35 2017/05/02 13:26:49 visa Exp $
# Standard stanzas config(8) can't run without
maxpartitions 16
file arch/octeon/dev/cn30xxipd.c iobus
file arch/octeon/dev/cn30xxpko.c iobus
file arch/octeon/dev/cn30xxasx.c iobus
-file arch/octeon/dev/cn30xxsmi.c iobus
define fdt {[early = 0]}
attach octrng at iobus
file arch/octeon/dev/octrng.c octrng
+device cn30xxsmi {}
+attach cn30xxsmi at fdt
+file arch/octeon/dev/cn30xxsmi.c cn30xxsmi
+
device cn30xxgmx {}
attach cn30xxgmx at iobus
file arch/octeon/dev/cn30xxgmx.c cn30xxgmx
-/* $OpenBSD: cn30xxgmx.c,v 1.33 2017/04/08 10:53:48 visa Exp $ */
+/* $OpenBSD: cn30xxgmx.c,v 1.34 2017/05/02 13:26:49 visa Exp $ */
/*
* Copyright (c) 2007 Internet Initiative Japan, Inc.
#include <machine/octeonvar.h>
#include <octeon/dev/iobusvar.h>
+#include <octeon/dev/cn30xxasxvar.h>
#include <octeon/dev/cn30xxciureg.h>
#include <octeon/dev/cn30xxgmxreg.h>
-#include <octeon/dev/cn30xxipdvar.h>
-#include <octeon/dev/cn30xxasxvar.h>
#include <octeon/dev/cn30xxgmxvar.h>
+#include <octeon/dev/cn30xxipdvar.h>
+#include <octeon/dev/cn30xxpipvar.h>
+#include <octeon/dev/cn30xxsmivar.h>
#define dprintf(...)
#define OCTEON_ETH_KASSERT KASSERT
}
int
-cn30xxgmx_port_phy_addr(int port)
+cn30xxgmx_get_phy_phandle(int port)
{
- static const int octeon_eth_phy_table[] = {
- /* portwell cam-0100 */
- 0x02, 0x03, 0x22
- };
char name[64];
- int phynode = 0;
- int portnode = -1;
- uint32_t phy = 0;
+ int node;
+ int phandle = 0;
snprintf(name, sizeof(name),
"/soc/pip@11800a0000000/interface@%x/ethernet@%x",
port / 16, port % 16);
- portnode = OF_finddevice(name);
- if (portnode != -1) {
- phy = OF_getpropint(portnode, "phy-handle", 0);
- if (phy != 0)
- phynode = OF_getnodebyphandle(phy);
- if (phynode != 0)
- return OF_getpropint(phynode, "reg", 0);
- }
-
- switch (octeon_boot_info->board_type) {
- case BOARD_TYPE_UBIQUITI_E100: /* port 0: 7, port 1: 6 */
- if (port > 2)
- return -1;
- return 7 - port;
-
- case BOARD_TYPE_UBIQUITI_E200:
- if (port >= 0 && port < 4)
- /* XXX RJ45/SFP combos use the second MDIO. */
- return port + 4; /* GMX0: eth[4-7] */
- else if (port >= 16 && port < 20)
- return port - 16; /* GMX1: eth[0-3] */
- return -1;
-
- case BOARD_TYPE_CN3010_EVB_HS5:
- if (port >= nitems(octeon_eth_phy_table))
- return -1;
- return octeon_eth_phy_table[port];
-
- default:
- return -1;
- }
+ node = OF_finddevice(name);
+ if (node != - 1)
+ phandle = OF_getpropint(node, "phy-handle", 0);
+ return phandle;
}
void
cn30xxgmx_attach(struct device *parent, struct device *self, void *aux)
{
- struct cn30xxgmx_softc *sc = (void *)self;
- struct iobus_attach_args *aa = aux;
struct cn30xxgmx_attach_args gmx_aa;
+ struct iobus_attach_args *aa = aux;
+ struct cn30xxgmx_port_softc *port_sc;
+ struct cn30xxgmx_softc *sc = (void *)self;
+ struct cn30xxsmi_softc *smi;
int i;
int phy_addr;
+ int port;
int status;
- struct cn30xxgmx_port_softc *port_sc;
printf("\n");
}
for (i = 0; i < sc->sc_nports; i++) {
- phy_addr = cn30xxgmx_port_phy_addr(
- GMX_PORT_NUM(sc->sc_unitno, i));
- if (phy_addr == -1)
+ port = GMX_PORT_NUM(sc->sc_unitno, i);
+ if (cn30xxsmi_get_phy(cn30xxgmx_get_phy_phandle(port), port,
+ &smi, &phy_addr))
continue;
port_sc = &sc->sc_ports[i];
port_sc->sc_port_gmx = sc;
- port_sc->sc_port_no = GMX_PORT_NUM(sc->sc_unitno, i);
+ port_sc->sc_port_no = port;
port_sc->sc_port_type = sc->sc_port_types[i];
port_sc->sc_port_ops = cn30xxgmx_port_ops[port_sc->sc_port_type];
status = bus_space_map(sc->sc_regt,
gmx_aa.ga_gmx = sc;
gmx_aa.ga_gmx_port = port_sc;
gmx_aa.ga_phy_addr = phy_addr;
+ gmx_aa.ga_smi = smi;
config_found(self, &gmx_aa, cn30xxgmx_print);
-/* $OpenBSD: cn30xxgmxvar.h,v 1.6 2016/06/09 15:29:22 visa Exp $ */
+/* $OpenBSD: cn30xxgmxvar.h,v 1.7 2017/05/02 13:26:49 visa Exp $ */
/*
* Copyright (c) 2007 Internet Initiative Japan, Inc.
const char *ga_name;
int ga_portno;
int ga_port_type;
+ struct cn30xxsmi_softc *ga_smi;
int ga_phy_addr;
struct cn30xxgmx_softc *ga_gmx;
-/* $OpenBSD: cn30xxsmi.c,v 1.3 2014/08/11 18:08:17 miod Exp $ */
+/* $OpenBSD: cn30xxsmi.c,v 1.4 2017/05/02 13:26:49 visa Exp $ */
/*
* Copyright (c) 2007 Internet Initiative Japan, Inc.
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
+#include <sys/stdint.h>
+#include <dev/ofw/fdt.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/fdt.h>
#include <machine/octeonvar.h>
-#include <octeon/dev/cn30xxfpavar.h>
-#include <octeon/dev/cn30xxpipreg.h>
#include <octeon/dev/cn30xxsmireg.h>
#include <octeon/dev/cn30xxsmivar.h>
+int cn30xxsmi_match(struct device *, void *, void *);
+void cn30xxsmi_attach(struct device *, struct device *, void *);
+
void cn30xxsmi_enable(struct cn30xxsmi_softc *);
-/* XXX */
+const struct cfattach cn30xxsmi_ca = {
+ sizeof(struct cn30xxsmi_softc), cn30xxsmi_match, cn30xxsmi_attach
+};
+
+struct cfdriver cn30xxsmi_cd = {
+ NULL, "cn30xxsmi", DV_DULL
+};
+
+static SLIST_HEAD(, cn30xxsmi_softc) smi_list =
+ SLIST_HEAD_INITIALIZER(smi_list);
+
+#define _SMI_RD8(sc, off) \
+ bus_space_read_8((sc)->sc_regt, (sc)->sc_regh, (off))
+#define _SMI_WR8(sc, off, v) \
+ bus_space_write_8((sc)->sc_regt, (sc)->sc_regh, (off), (v))
+
+int
+cn30xxsmi_match(struct device *parent, void *match, void *aux)
+{
+ struct fdt_attach_args *faa = aux;
+
+ return OF_is_compatible(faa->fa_node, "cavium,octeon-3860-mdio");
+}
+
void
-cn30xxsmi_init(struct cn30xxsmi_attach_args *aa,
- struct cn30xxsmi_softc **rsc)
+cn30xxsmi_attach(struct device *parent, struct device *self, void *aux)
{
- struct cn30xxsmi_softc *sc;
- int status;
+ struct fdt_attach_args *faa = aux;
+ struct cn30xxsmi_softc *sc = (struct cn30xxsmi_softc *)self;
- sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
- if (sc == NULL)
- panic("can't allocate memory: %s", __func__);
+ if (faa->fa_nreg != 1)
+ return;
- sc->sc_port = aa->aa_port;
- sc->sc_regt = aa->aa_regt;
+ sc->sc_node = faa->fa_node;
+ sc->sc_regt = faa->fa_iot;
- status = bus_space_map(sc->sc_regt, SMI_BASE, SMI_SIZE, 0,
- &sc->sc_regh);
- if (status != 0)
- panic("can't map %s space", "smi register");
+ if (bus_space_map(sc->sc_regt, faa->fa_reg[0].addr, faa->fa_reg[0].size,
+ 0, &sc->sc_regh)) {
+ printf(": could not map registers\n");
+ return;
+ }
- cn30xxsmi_enable(sc);
+ SLIST_INSERT_HEAD(&smi_list, sc, sc_link);
- *rsc = sc;
-}
+ printf("\n");
-#define _SMI_RD8(sc, off) \
- bus_space_read_8((sc)->sc_regt, (sc)->sc_regh, (off))
-#define _SMI_WR8(sc, off, v) \
- bus_space_write_8((sc)->sc_regt, (sc)->sc_regh, (off), (v))
+ _SMI_WR8(sc, SMI_CLK_OFFSET, 0x1464);
+ _SMI_WR8(sc, SMI_EN_OFFSET, SMI_EN_EN);
+}
int
cn30xxsmi_read(struct cn30xxsmi_softc *sc, int phy_addr, int reg)
}
}
-void
-cn30xxsmi_enable(struct cn30xxsmi_softc *sc)
+int
+cn30xxsmi_get_phy(int phandle, int port, struct cn30xxsmi_softc **psmi,
+ int *preg)
{
- _SMI_WR8(sc, SMI_EN_OFFSET, SMI_EN_EN);
-}
+ /* PHY addresses for Portwell CAM-0100 */
+ static const int cam0100_phys[] = {
+ 0x02, 0x03, 0x22
+ };
+
+ struct cn30xxsmi_softc *smi;
+ int parent, phynode;
+ int reg;
+
+ if (phandle != 0) {
+ phynode = OF_getnodebyphandle(phandle);
+ if (phynode == 0)
+ return ENOENT;
+ reg = OF_getpropint(phynode, "reg", UINT32_MAX);
+ if (reg == UINT32_MAX)
+ return ENOENT;
+
+ parent = OF_parent(phynode);
+ SLIST_FOREACH(smi, &smi_list, sc_link) {
+ if (smi->sc_node == parent)
+ goto found;
+ }
+ return ENOENT;
+ } else {
+ smi = SLIST_FIRST(&smi_list);
+ if (smi == NULL)
+ return ENOENT;
+
+ switch (octeon_boot_info->board_type) {
+ case BOARD_TYPE_UBIQUITI_E100:
+ if (port > 2)
+ return ENOENT;
+ reg = 7 - port;
+ break;
+ case BOARD_TYPE_CN3010_EVB_HS5:
+ if (port >= nitems(cam0100_phys))
+ return ENOENT;
+ reg = cam0100_phys[port];
+ break;
+ default:
+ return ENOENT;
+ }
+ }
-void
-cn30xxsmi_set_clock(struct cn30xxsmi_softc *sc, uint64_t clock)
-{
- _SMI_WR8(sc, SMI_CLK_OFFSET, clock);
+found:
+ *psmi = smi;
+ *preg = reg;
+ return 0;
}
-
* DONT EDIT THIS FILE
*/
-/* $OpenBSD: cn30xxsmireg.h,v 1.1 2011/06/16 11:22:30 syuu Exp $ */
+/* $OpenBSD: cn30xxsmireg.h,v 1.2 2017/05/02 13:26:49 visa Exp $ */
/*
* Copyright (c) 2007 Internet Initiative Japan, Inc.
#ifndef _CN30XXSMIREG_H_
#define _CN30XXSMIREG_H_
-#define SMI_CMD 0x0001180000001800ULL
-#define SMI_WR_DAT 0x0001180000001808ULL
-#define SMI_RD_DAT 0x0001180000001810ULL
-#define SMI_CLK 0x0001180000001818ULL
-#define SMI_EN 0x0001180000001820ULL
-
#define SMI_CMD_OFFSET 0x00ULL
#define SMI_WR_DAT_OFFSET 0x08ULL
#define SMI_RD_DAT_OFFSET 0x10ULL
#define SMI_CLK_OFFSET 0x18ULL
#define SMI_EN_OFFSET 0x20ULL
-#define SMI_BASE 0x0001180000001800ULL
-#define SMI_SIZE 0x028ULL
-
/* SMI CMD */
#define SMI_CMD_63_17 0xfffffffffffe0000ULL
#define SMI_CMD_PHY_OP 0x0000000000010000ULL
-/* $OpenBSD: cn30xxsmivar.h,v 1.2 2011/06/24 02:13:23 yasuoka Exp $ */
+/* $OpenBSD: cn30xxsmivar.h,v 1.3 2017/05/02 13:26:49 visa Exp $ */
/*
* Copyright (c) 2007 Internet Initiative Japan, Inc.
#ifndef _CN30XXSMIVAR_H_
#define _CN30XXSMIVAR_H_
-/* XXX */
struct cn30xxsmi_softc {
- int sc_port;
+ struct device sc_dev;
+ int sc_node;
+
bus_space_tag_t sc_regt;
bus_space_handle_t sc_regh;
-};
-/* XXX */
-struct cn30xxsmi_attach_args {
- int aa_port;
- bus_space_tag_t aa_regt;
+ SLIST_ENTRY(cn30xxsmi_softc) sc_link;
};
-void cn30xxsmi_init(struct cn30xxsmi_attach_args *,
- struct cn30xxsmi_softc **);
-int cn30xxsmi_read(struct cn30xxsmi_softc *, int, int);
-void cn30xxsmi_write(struct cn30xxsmi_softc *, int, int, int);
-void cn30xxsmi_set_clock(struct cn30xxsmi_softc *, uint64_t);
+int cn30xxsmi_read(struct cn30xxsmi_softc *, int, int);
+void cn30xxsmi_write(struct cn30xxsmi_softc *, int, int, int);
+
+int cn30xxsmi_get_phy(int, int, struct cn30xxsmi_softc **, int *);
#endif
-/* $OpenBSD: if_cnmac.c,v 1.63 2017/04/02 15:25:05 visa Exp $ */
+/* $OpenBSD: if_cnmac.c,v 1.64 2017/05/02 13:26:49 visa Exp $ */
/*
* Copyright (c) 2007 Internet Initiative Japan, Inc.
sc->sc_port_type = ga->ga_port_type;
sc->sc_gmx = ga->ga_gmx;
sc->sc_gmx_port = ga->ga_gmx_port;
+ sc->sc_smi = ga->ga_smi;
sc->sc_phy_addr = ga->ga_phy_addr;
sc->sc_init_flag = 0;
octeon_eth_pip_init(sc);
octeon_eth_ipd_init(sc);
octeon_eth_pko_init(sc);
- octeon_eth_smi_init(sc);
sc->sc_gmx_port->sc_ipd = sc->sc_ipd;
sc->sc_gmx_port->sc_port_mii = &sc->sc_mii;
cn30xxpko_init(&pko_aa, &sc->sc_pko);
}
-void
-octeon_eth_smi_init(struct octeon_eth_softc *sc)
-{
- struct cn30xxsmi_attach_args smi_aa;
-
- smi_aa.aa_port = sc->sc_port;
- smi_aa.aa_regt = sc->sc_regt;
- cn30xxsmi_init(&smi_aa, &sc->sc_smi);
- cn30xxsmi_set_clock(sc->sc_smi, 0x1464ULL); /* XXX */
-}
-
/* ---- XXX */
void