Module Name: src Committed By: jmcneill Date: Thu Jul 16 18:39:19 UTC 2020
Modified Files: src/sys/arch/evbmips/conf: OCTEON src/sys/arch/mips/conf: files.octeon Added Files: src/sys/arch/mips/cavium/dev: octeon_cib.c Log Message: Add driver for Cavium Interrupt Bus. To generate a diff of this commit: cvs rdiff -u -r1.3 -r1.4 src/sys/arch/evbmips/conf/OCTEON cvs rdiff -u -r0 -r1.1 src/sys/arch/mips/cavium/dev/octeon_cib.c cvs rdiff -u -r1.10 -r1.11 src/sys/arch/mips/conf/files.octeon Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/evbmips/conf/OCTEON diff -u src/sys/arch/evbmips/conf/OCTEON:1.3 src/sys/arch/evbmips/conf/OCTEON:1.4 --- src/sys/arch/evbmips/conf/OCTEON:1.3 Thu Jul 16 16:39:54 2020 +++ src/sys/arch/evbmips/conf/OCTEON Thu Jul 16 18:39:18 2020 @@ -1,11 +1,11 @@ -# $NetBSD: OCTEON,v 1.3 2020/07/16 16:39:54 jmcneill Exp $ +# $NetBSD: OCTEON,v 1.4 2020/07/16 18:39:18 jmcneill Exp $ include "arch/mips/conf/std.octeon" include "arch/evbmips/conf/files.octeon" #options INCLUDE_CONFIG_FILE # embed config file in kernel binary -#ident "ERLITE-$Revision: 1.3 $" +#ident "ERLITE-$Revision: 1.4 $" maxusers 32 @@ -119,14 +119,15 @@ bootbus0 at mainbus? simplebus* at fdt? pass 0 octintc* at fdt? pass 1 +octcib* at fdt? pass 2 com* at iobus? com* at fdt? octsmi* at iobus? # MDIO controller -octsmi* at fdt? pass 2 +octsmi* at fdt? pass 3 octpip* at iobus? # PIP packet processing controller -octpip* at fdt? pass 3 +octpip* at fdt? pass 4 octgmx* at octpip? cnmac* at octgmx? Index: src/sys/arch/mips/conf/files.octeon diff -u src/sys/arch/mips/conf/files.octeon:1.10 src/sys/arch/mips/conf/files.octeon:1.11 --- src/sys/arch/mips/conf/files.octeon:1.10 Thu Jul 16 11:49:38 2020 +++ src/sys/arch/mips/conf/files.octeon Thu Jul 16 18:39:19 2020 @@ -1,4 +1,4 @@ -# $NetBSD: files.octeon,v 1.10 2020/07/16 11:49:38 jmcneill Exp $ +# $NetBSD: files.octeon,v 1.11 2020/07/16 18:39:19 jmcneill Exp $ file arch/mips/mips/locore_octeon.S file arch/mips/mips/bus_dma.c @@ -32,6 +32,10 @@ device octintc attach octintc at fdt file arch/mips/cavium/dev/octeon_intc.c octintc +device octcib +attach octcib at fdt +file arch/mips/cavium/dev/octeon_cib.c octcib + # I/O Bus device iobus {} @@ -64,10 +68,6 @@ device octmpi: spibus attach octmpi at iobus file arch/mips/cavium/dev/octeon_mpi.c octmpi -device octcib {} -attach octcib at iobus -file arch/mips/cavium/dev/octeon_cib.c octcib - device octcit {} attach octcit at iobus file arch/mips/cavium/dev/octeon_cit.c octcit Added files: Index: src/sys/arch/mips/cavium/dev/octeon_cib.c diff -u /dev/null src/sys/arch/mips/cavium/dev/octeon_cib.c:1.1 --- /dev/null Thu Jul 16 18:39:19 2020 +++ src/sys/arch/mips/cavium/dev/octeon_cib.c Thu Jul 16 18:39:19 2020 @@ -0,0 +1,261 @@ +/* $NetBSD: octeon_cib.c,v 1.1 2020/07/16 18:39:19 jmcneill Exp $ */ + +/*- + * Copyright (c) 2020 Jared D. McNeill <jmcne...@invisible.ca> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "opt_multiprocessor.h" + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: octeon_cib.c,v 1.1 2020/07/16 18:39:19 jmcneill Exp $"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/device.h> +#include <sys/intr.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/kmem.h> + +#include <dev/fdt/fdtvar.h> + +#include <arch/mips/cavium/octeonvar.h> + +static int octeon_cib_match(device_t, cfdata_t, void *); +static void octeon_cib_attach(device_t, device_t, void *); + +static void * octeon_cib_establish(device_t, u_int *, int, int, + int (*)(void *), void *); +static void octeon_cib_disestablish(device_t, void *); +static bool octeon_cib_intrstr(device_t, u_int *, char *, size_t); + +static int octeon_cib_intr(void *); + +struct fdtbus_interrupt_controller_func octeon_cib_funcs = { + .establish = octeon_cib_establish, + .disestablish = octeon_cib_disestablish, + .intrstr = octeon_cib_intrstr +}; + +struct octeon_cib_intr { + bool ih_mpsafe; + int ih_type; + int (*ih_func)(void *); + void *ih_arg; + uint64_t ih_mask; +}; + +struct octeon_cib_softc { + device_t sc_dev; + int sc_phandle; + bus_space_tag_t sc_bst; + bus_space_handle_t sc_bsh_raw; + bus_space_handle_t sc_bsh_en; + + struct octeon_cib_intr *sc_intr; + u_int sc_nintr; +}; + +#define CIB_READ_RAW(sc) \ + bus_space_read_8((sc)->sc_bst, (sc)->sc_bsh_raw, 0) +#define CIB_WRITE_RAW(sc, val) \ + bus_space_write_8((sc)->sc_bst, (sc)->sc_bsh_raw, 0, (val)) +#define CIB_READ_EN(sc) \ + bus_space_read_8((sc)->sc_bst, (sc)->sc_bsh_en, 0) +#define CIB_WRITE_EN(sc, val) \ + bus_space_write_8((sc)->sc_bst, (sc)->sc_bsh_en, 0, (val)) + +CFATTACH_DECL_NEW(octcib, sizeof(struct octeon_cib_softc), + octeon_cib_match, octeon_cib_attach, NULL, NULL); + +static const struct of_compat_data compat_data[] = { + { "cavium,octeon-7130-cib", 1 }, + { NULL } +}; + +static int +octeon_cib_match(device_t parent, cfdata_t cf, void *aux) +{ + struct fdt_attach_args * const faa = aux; + + return of_match_compat_data(faa->faa_phandle, compat_data); +} + +static void +octeon_cib_attach(device_t parent, device_t self, void *aux) +{ + struct octeon_cib_softc * const sc = device_private(self); + struct fdt_attach_args * const faa = aux; + const int phandle = faa->faa_phandle; + char intrstr[128]; + bus_addr_t addr; + bus_size_t size; + u_int max_bits; + int error; + void *ih; + + sc->sc_dev = self; + sc->sc_phandle = phandle; + sc->sc_bst = faa->faa_bst; + + if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0 || + bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh_raw) != 0) { + aprint_error(": couldn't map RAW register\n"); + return; + } + if (fdtbus_get_reg(phandle, 1, &addr, &size) != 0 || + bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh_en) != 0) { + aprint_error(": couldn't map EN register\n"); + return; + } + + if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) { + aprint_error(": failed to decode interrupt\n"); + return; + } + + if (of_getprop_uint32(phandle, "cavium,max-bits", &max_bits) != 0) { + aprint_error(": missing 'cavium,max-bits' property\n"); + return; + } + if (max_bits == 0 || max_bits > 64) { + aprint_error(": 'cavium,max-bits' value out of range\n"); + return; + } + + sc->sc_intr = kmem_zalloc(sizeof(*sc->sc_intr) * max_bits, KM_SLEEP); + sc->sc_nintr = max_bits; + + error = fdtbus_register_interrupt_controller(self, phandle, + &octeon_cib_funcs); + if (error != 0) { + aprint_error(": couldn't register with fdtbus: %d\n", error); + return; + } + + aprint_naive("\n"); + aprint_normal(": CIB\n"); + + CIB_WRITE_EN(sc, 0); + CIB_WRITE_RAW(sc, ~0ULL); + + ih = fdtbus_intr_establish(phandle, 0, IPL_SCHED, FDT_INTR_MPSAFE, + octeon_cib_intr, sc); + if (ih == NULL) { + aprint_error_dev(self, "couldn't establish interrupt on %s\n", + intrstr); + return; + } + aprint_normal_dev(self, "interrupting on %s\n", intrstr); +} + +static void * +octeon_cib_establish(device_t dev, u_int *specifier, int ipl, int flags, + int (*func)(void *), void *arg) +{ + struct octeon_cib_softc * const sc = device_private(dev); + struct octeon_cib_intr *ih; + uint64_t val; + + /* 1st cell is the bit number in the CIB* registers */ + /* 2nd cell is the triggering setting */ + const int bit = be32toh(specifier[0]); + const int type = (be32toh(specifier[1]) & 0x3) ? IST_EDGE : IST_LEVEL; + + if (bit > sc->sc_nintr) { + aprint_error_dev(dev, "bit %d out of range\n", bit); + return NULL; + } + + ih = &sc->sc_intr[bit]; + ih->ih_mpsafe = (flags & FDT_INTR_MPSAFE) != 0; + ih->ih_type = type; + ih->ih_func = func; + ih->ih_arg = arg; + ih->ih_mask = __BIT(bit); + + val = CIB_READ_EN(sc); + val |= ih->ih_mask; + CIB_WRITE_EN(sc, val); + + return ih; +} + +static void +octeon_cib_disestablish(device_t dev, void *ih_cookie) +{ + struct octeon_cib_softc * const sc = device_private(dev); + struct octeon_cib_intr *ih = ih_cookie; + uint64_t val; + + val = CIB_READ_EN(sc); + val &= ~ih->ih_mask; + CIB_WRITE_EN(sc, val); +} + +static bool +octeon_cib_intrstr(device_t dev, u_int *specifier, char *buf, + size_t buflen) +{ + /* 1st cell is the bit number in the CIB* registers */ + const int bit = be32toh(specifier[0]); + + snprintf(buf, buflen, "%s intr %d", device_xname(dev), bit); + + return true; +} + +static int +octeon_cib_intr(void *priv) +{ + struct octeon_cib_softc * const sc = priv; + struct octeon_cib_intr *ih; + uint64_t pend; + int n, rv = 0; + + pend = CIB_READ_RAW(sc); + pend &= CIB_READ_EN(sc); + + while ((n = ffs64(pend)) != 0) { + ih = &sc->sc_intr[n - 1]; + KASSERT(ih->ih_mask == __BIT(n - 1)); + + if (ih->ih_type == IST_EDGE) + CIB_WRITE_RAW(sc, ih->ih_mask); /* ack */ + +#ifdef MULTIPROCESSOR + if (!ih->ih_mpsafe) { + KERNEL_LOCK(1, NULL); + rv |= ih->ih_func(ih->ih_arg); + KERNEL_UNLOCK_ONE(NULL); + } else +#endif + rv |= ih->ih_func(ih->ih_arg); + + pend &= ~ih->ih_mask; + } + + return rv; +}