summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/octeon/conf/GENERIC5
-rw-r--r--sys/arch/octeon/conf/RAMDISK5
-rw-r--r--sys/arch/octeon/conf/files.octeon8
-rw-r--r--sys/arch/octeon/dev/octeon_iobus.c18
-rw-r--r--sys/arch/octeon/dev/simplebus.c247
-rw-r--r--sys/arch/octeon/dev/simplebusvar.h34
-rw-r--r--sys/arch/octeon/include/fdt.h37
7 files changed, 349 insertions, 5 deletions
diff --git a/sys/arch/octeon/conf/GENERIC b/sys/arch/octeon/conf/GENERIC
index 593f9a2b231..8e76f1752b5 100644
--- a/sys/arch/octeon/conf/GENERIC
+++ b/sys/arch/octeon/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.28 2016/07/05 12:53:40 visa Exp $
+# $OpenBSD: GENERIC,v 1.29 2016/12/08 16:24:51 visa Exp $
#
# For further information on compiling OpenBSD kernels, see the config(8)
# man page.
@@ -33,6 +33,9 @@ clock0 at mainbus0
iobus0 at mainbus0
uartbus0 at mainbus0
+simplebus* at fdt?
+simplebus* at iobus?
+
octrtc0 at mainbus0
octcf0 at iobus0
diff --git a/sys/arch/octeon/conf/RAMDISK b/sys/arch/octeon/conf/RAMDISK
index 400c9be76d1..8f07175cbe6 100644
--- a/sys/arch/octeon/conf/RAMDISK
+++ b/sys/arch/octeon/conf/RAMDISK
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK,v 1.26 2016/07/05 12:53:40 visa Exp $
+# $OpenBSD: RAMDISK,v 1.27 2016/12/08 16:24:51 visa Exp $
machine octeon mips64
maxusers 4
@@ -41,6 +41,9 @@ uartbus0 at mainbus0
com0 at uartbus0
com1 at uartbus0
+simplebus* at fdt?
+simplebus* at iobus?
+
octrtc0 at mainbus0
pcibus* at iobus0
diff --git a/sys/arch/octeon/conf/files.octeon b/sys/arch/octeon/conf/files.octeon
index 5fe9f3235a7..eead8c0dfac 100644
--- a/sys/arch/octeon/conf/files.octeon
+++ b/sys/arch/octeon/conf/files.octeon
@@ -1,4 +1,4 @@
-# $OpenBSD: files.octeon,v 1.31 2016/07/05 12:53:40 visa Exp $
+# $OpenBSD: files.octeon,v 1.32 2016/12/08 16:24:51 visa Exp $
# Standard stanzas config(8) can't run without
maxpartitions 16
@@ -67,6 +67,12 @@ 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]}
+
+device simplebus: fdt
+attach simplebus at fdt, iobus
+file arch/octeon/dev/simplebus.c simplebus
# On-board USB
attach dwctwo at iobus with octdwctwo
diff --git a/sys/arch/octeon/dev/octeon_iobus.c b/sys/arch/octeon/dev/octeon_iobus.c
index cf3bc4bfaa9..1c55d1a96cc 100644
--- a/sys/arch/octeon/dev/octeon_iobus.c
+++ b/sys/arch/octeon/dev/octeon_iobus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: octeon_iobus.c,v 1.16 2016/06/22 13:09:35 visa Exp $ */
+/* $OpenBSD: octeon_iobus.c,v 1.17 2016/12/08 16:24:51 visa Exp $ */
/*
* Copyright (c) 2000-2004 Opsycon AB (www.opsycon.se)
@@ -40,7 +40,11 @@
#include <sys/proc.h>
#include <sys/atomic.h>
+#include <dev/ofw/fdt.h>
+#include <dev/ofw/openfirm.h>
+
#include <machine/autoconf.h>
+#include <machine/fdt.h>
#include <machine/intr.h>
#include <machine/octeonvar.h>
#include <machine/octeonreg.h>
@@ -204,9 +208,10 @@ void
iobusattach(struct device *parent, struct device *self, void *aux)
{
struct iobus_attach_args aa;
+ struct fdt_attach_args fa;
struct octeon_config oc;
struct device *sc = self;
- int chipid, i, ngmx;
+ int chipid, i, ngmx, soc;
/*
* Map and setup CIU control registers.
@@ -256,6 +261,15 @@ iobusattach(struct device *parent, struct device *self, void *aux)
aa.aa_unitno = i;
config_found_sm(self, &aa, iobusprint, iobussubmatch);
}
+
+ if ((soc = OF_finddevice("/soc")) != -1) {
+ memset(&fa, 0, sizeof(fa));
+ fa.fa_name = "";
+ fa.fa_node = soc;
+ fa.fa_iot = &iobus_tag;
+ fa.fa_dmat = &iobus_bus_dma_tag;
+ config_found(self, &fa, NULL);
+ }
}
int
diff --git a/sys/arch/octeon/dev/simplebus.c b/sys/arch/octeon/dev/simplebus.c
new file mode 100644
index 00000000000..9acbe649633
--- /dev/null
+++ b/sys/arch/octeon/dev/simplebus.c
@@ -0,0 +1,247 @@
+/* $OpenBSD: simplebus.c,v 1.1 2016/12/08 16:24:51 visa Exp $ */
+
+/*
+ * Copyright (c) 2016 Patrick Wildt <patrick@blueri.se>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/fdt.h>
+
+#include <machine/fdt.h>
+#include <octeon/dev/simplebusvar.h>
+
+int simplebus_match(struct device *, void *, void *);
+void simplebus_attach(struct device *, struct device *, void *);
+
+void simplebus_attach_node(struct device *, int);
+int simplebus_bs_map(bus_space_tag_t, bus_addr_t, bus_size_t,
+ int, bus_space_handle_t *);
+
+const struct cfattach simplebus_ca = {
+ sizeof(struct simplebus_softc), simplebus_match, simplebus_attach
+};
+
+struct cfdriver simplebus_cd = {
+ NULL, "simplebus", DV_DULL
+};
+
+/*
+ * Simplebus is a generic bus with no special casings.
+ */
+int
+simplebus_match(struct device *parent, void *cfdata, void *aux)
+{
+ struct fdt_attach_args *fa = (struct fdt_attach_args *)aux;
+
+ /* Guard against non-fdt attach on iobus(4). */
+ if (strlen(fa->fa_name) > 0)
+ return (0);
+
+ if (fa->fa_node == 0)
+ return (0);
+
+ if (!OF_is_compatible(fa->fa_node, "simple-bus"))
+ return (0);
+
+ return (1);
+}
+
+void
+simplebus_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct simplebus_softc *sc = (struct simplebus_softc *)self;
+ struct fdt_attach_args *fa = (struct fdt_attach_args *)aux;
+ char name[32];
+ int node;
+
+ sc->sc_node = fa->fa_node;
+ sc->sc_iot = fa->fa_iot;
+ sc->sc_dmat = fa->fa_dmat;
+ sc->sc_acells = OF_getpropint(sc->sc_node, "#address-cells",
+ fa->fa_acells);
+ sc->sc_scells = OF_getpropint(sc->sc_node, "#size-cells",
+ fa->fa_scells);
+ sc->sc_pacells = fa->fa_acells;
+ sc->sc_pscells = fa->fa_scells;
+
+ if (OF_getprop(sc->sc_node, "name", name, sizeof(name)) > 0) {
+ name[sizeof(name) - 1] = 0;
+ printf(": \"%s\"", name);
+ }
+
+ printf("\n");
+
+ memcpy(&sc->sc_bus, sc->sc_iot, sizeof(sc->sc_bus));
+ sc->sc_bus.bus_private = sc;
+ sc->sc_bus._space_map = simplebus_bs_map;
+
+ sc->sc_rangeslen = OF_getproplen(sc->sc_node, "ranges");
+ if (sc->sc_rangeslen > 0 && !(sc->sc_rangeslen % sizeof(uint32_t))) {
+ sc->sc_ranges = malloc(sc->sc_rangeslen, M_TEMP, M_WAITOK);
+ OF_getpropintarray(sc->sc_node, "ranges", sc->sc_ranges,
+ sc->sc_rangeslen);
+ }
+
+ /* Scan the whole tree. */
+ sc->sc_early = 1;
+ for (node = OF_child(sc->sc_node); node; node = OF_peer(node))
+ simplebus_attach_node(self, node);
+
+ sc->sc_early = 0;
+ for (node = OF_child(sc->sc_node); node; node = OF_peer(node))
+ simplebus_attach_node(self, node);
+}
+
+int
+simplebus_submatch(struct device *self, void *match, void *aux)
+{
+ struct simplebus_softc *sc = (struct simplebus_softc *)self;
+ struct cfdata *cf = match;
+
+ if (cf->cf_loc[0] == sc->sc_early)
+ return (*cf->cf_attach->ca_match)(self, match, aux);
+ return 0;
+}
+
+/*
+ * Look for a driver that wants to be attached to this node.
+ */
+void
+simplebus_attach_node(struct device *self, int node)
+{
+ struct simplebus_softc *sc = (struct simplebus_softc *)self;
+ struct fdt_attach_args fa;
+ char buffer[128];
+ int i, len, line;
+ uint32_t *cell, *reg;
+
+ if (!OF_getprop(node, "compatible", buffer, sizeof(buffer)))
+ return;
+
+ if (OF_getprop(node, "status", buffer, sizeof(buffer)))
+ if (!strcmp(buffer, "disabled"))
+ return;
+
+ memset(&fa, 0, sizeof(fa));
+ fa.fa_name = "";
+ fa.fa_node = node;
+ fa.fa_iot = &sc->sc_bus;
+ fa.fa_dmat = sc->sc_dmat;
+ fa.fa_acells = sc->sc_acells;
+ fa.fa_scells = sc->sc_scells;
+
+ len = OF_getproplen(node, "reg");
+ line = (sc->sc_acells + sc->sc_scells) * sizeof(uint32_t);
+ if (len > 0 && line > 0 && (len % line) == 0) {
+ reg = malloc(len, M_TEMP, M_WAITOK);
+ OF_getpropintarray(node, "reg", reg, len);
+
+ fa.fa_reg = malloc((len / line) * sizeof(struct fdt_reg),
+ M_DEVBUF, M_WAITOK | M_ZERO);
+ fa.fa_nreg = (len / line);
+
+ for (i = 0, cell = reg; i < len / line; i++) {
+ if (sc->sc_acells >= 1)
+ fa.fa_reg[i].addr = cell[0];
+ if (sc->sc_acells == 2) {
+ fa.fa_reg[i].addr <<= 32;
+ fa.fa_reg[i].addr |= cell[1];
+ }
+ cell += sc->sc_acells;
+ if (sc->sc_scells >= 1)
+ fa.fa_reg[i].size = cell[0];
+ if (sc->sc_scells == 2) {
+ fa.fa_reg[i].size <<= 32;
+ fa.fa_reg[i].size |= cell[1];
+ }
+ cell += sc->sc_scells;
+ }
+
+ free(reg, M_TEMP, len);
+ }
+
+ len = OF_getproplen(node, "interrupts");
+ if (len > 0 && (len % sizeof(uint32_t)) == 0) {
+ fa.fa_intr = malloc(len, M_DEVBUF, M_WAITOK);
+ fa.fa_nintr = len / sizeof(uint32_t);
+
+ OF_getpropintarray(node, "interrupts", fa.fa_intr, len);
+ }
+
+ config_found_sm(self, &fa, NULL, simplebus_submatch);
+
+ free(fa.fa_reg, M_DEVBUF, fa.fa_nreg * sizeof(struct fdt_reg));
+ free(fa.fa_intr, M_DEVBUF, fa.fa_nintr * sizeof(uint32_t));
+}
+
+/*
+ * Translate memory address if needed.
+ */
+int
+simplebus_bs_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size,
+ int flag, bus_space_handle_t *bshp)
+{
+ struct simplebus_softc *sc = t->bus_private;
+ uint64_t addr, rfrom, rto, rsize;
+ uint32_t *range;
+ int parent, rlen, rone;
+
+ addr = bpa;
+ parent = OF_parent(sc->sc_node);
+ if (parent == 0)
+ return bus_space_map(sc->sc_iot, addr, size, flag, bshp);
+
+ if (sc->sc_rangeslen < 0)
+ return EINVAL;
+ if (sc->sc_rangeslen == 0)
+ return bus_space_map(sc->sc_iot, addr, size, flag, bshp);
+
+ rlen = sc->sc_rangeslen / sizeof(uint32_t);
+ rone = sc->sc_pacells + sc->sc_acells + sc->sc_scells;
+
+ /* For each range. */
+ for (range = sc->sc_ranges; rlen >= rone; rlen -= rone, range += rone) {
+ /* Extract from and size, so we can see if we fit. */
+ rfrom = range[0];
+ if (sc->sc_acells == 2)
+ rfrom = (rfrom << 32) + range[1];
+ rsize = range[sc->sc_acells + sc->sc_pacells];
+ if (sc->sc_scells == 2)
+ rsize = (rsize << 32) +
+ range[sc->sc_acells + sc->sc_pacells + 1];
+
+ /* Try next, if we're not in the range. */
+ if (addr < rfrom || (addr + size) > (rfrom + rsize))
+ continue;
+
+ /* All good, extract to address and translate. */
+ rto = range[sc->sc_acells];
+ if (sc->sc_pacells == 2)
+ rto = (rto << 32) + range[sc->sc_acells + 1];
+
+ addr -= rfrom;
+ addr += rto;
+
+ return bus_space_map(sc->sc_iot, addr, size, flag, bshp);
+ }
+
+ return ESRCH;
+}
diff --git a/sys/arch/octeon/dev/simplebusvar.h b/sys/arch/octeon/dev/simplebusvar.h
new file mode 100644
index 00000000000..6445d386d2d
--- /dev/null
+++ b/sys/arch/octeon/dev/simplebusvar.h
@@ -0,0 +1,34 @@
+/* $OpenBSD: simplebusvar.h,v 1.1 2016/12/08 16:24:51 visa Exp $ */
+
+/*
+ * Copyright (c) 2016 Patrick Wildt <patrick@blueri.se>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+struct simplebus_softc {
+ struct device sc_dev;
+ int sc_node;
+ bus_space_tag_t sc_iot;
+ bus_dma_tag_t sc_dmat;
+ int sc_acells;
+ int sc_scells;
+ int sc_pacells;
+ int sc_pscells;
+ bus_space_t sc_bus;
+ int *sc_ranges;
+ int sc_rangeslen;
+ int sc_early;
+};
+
+extern void simplebus_attach(struct device *, struct device *, void *);
diff --git a/sys/arch/octeon/include/fdt.h b/sys/arch/octeon/include/fdt.h
new file mode 100644
index 00000000000..a55251c04fe
--- /dev/null
+++ b/sys/arch/octeon/include/fdt.h
@@ -0,0 +1,37 @@
+/* $OpenBSD: fdt.h,v 1.1 2016/12/08 16:24:51 visa Exp $ */
+
+/*
+ * Copyright (c) 2016 Patrick Wildt <patrick@blueri.se>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __OCTEON_FDT_H__
+#define __OCTEON_FDT_H__
+
+#include <machine/bus.h>
+
+struct fdt_attach_args {
+ const char *fa_name;
+ int fa_node;
+ bus_space_tag_t fa_iot;
+ bus_dma_tag_t fa_dmat;
+ struct fdt_reg *fa_reg;
+ int fa_nreg;
+ uint32_t *fa_intr;
+ int fa_nintr;
+ int fa_acells;
+ int fa_scells;
+};
+
+#endif /* __OCTEON_FDT_H__ */