summaryrefslogtreecommitdiff
path: root/sys/arch/octeon/dev/cn30xxsmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/octeon/dev/cn30xxsmi.c')
-rw-r--r--sys/arch/octeon/dev/cn30xxsmi.c135
1 files changed, 100 insertions, 35 deletions
diff --git a/sys/arch/octeon/dev/cn30xxsmi.c b/sys/arch/octeon/dev/cn30xxsmi.c
index a2244113aca..9b128cc015a 100644
--- a/sys/arch/octeon/dev/cn30xxsmi.c
+++ b/sys/arch/octeon/dev/cn30xxsmi.c
@@ -1,4 +1,4 @@
-/* $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.
@@ -28,47 +28,71 @@
#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)
@@ -123,15 +147,56 @@ cn30xxsmi_write(struct cn30xxsmi_softc *sc, int phy_addr, int reg, int value)
}
}
-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;
}
-