diff options
-rw-r--r-- | sys/arch/octeon/conf/GENERIC | 5 | ||||
-rw-r--r-- | sys/arch/octeon/conf/RAMDISK | 5 | ||||
-rw-r--r-- | sys/arch/octeon/conf/files.octeon | 8 | ||||
-rw-r--r-- | sys/arch/octeon/dev/octeon_iobus.c | 18 | ||||
-rw-r--r-- | sys/arch/octeon/dev/simplebus.c | 247 | ||||
-rw-r--r-- | sys/arch/octeon/dev/simplebusvar.h | 34 | ||||
-rw-r--r-- | sys/arch/octeon/include/fdt.h | 37 |
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__ */ |