Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/sunxi sunxi: nmi: add support for #interrupt-ce...



details:   https://anonhg.NetBSD.org/src/rev/f272949c8e94
branches:  trunk
changeset: 1024867:f272949c8e94
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sun Nov 07 17:13:38 2021 +0000

description:
sunxi: nmi: add support for #interrupt-cells 3 bindings

diffstat:

 sys/arch/arm/sunxi/sunxi_nmi.c |  84 +++++++++++++++++++++++++++++++++++------
 1 files changed, 71 insertions(+), 13 deletions(-)

diffs (155 lines):

diff -r 8b0542d692fe -r f272949c8e94 sys/arch/arm/sunxi/sunxi_nmi.c
--- a/sys/arch/arm/sunxi/sunxi_nmi.c    Sun Nov 07 17:13:26 2021 +0000
+++ b/sys/arch/arm/sunxi/sunxi_nmi.c    Sun Nov 07 17:13:38 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_nmi.c,v 1.11 2021/01/27 03:10:20 thorpej Exp $ */
+/* $NetBSD: sunxi_nmi.c,v 1.12 2021/11/07 17:13:38 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2018 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -29,7 +29,7 @@
 #define        _INTR_PRIVATE
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_nmi.c,v 1.11 2021/01/27 03:10:20 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_nmi.c,v 1.12 2021/11/07 17:13:38 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -105,6 +105,9 @@
        bus_space_handle_t sc_bsh;
        int sc_phandle;
 
+       u_int sc_intr_nmi;
+       u_int sc_intr_cells;
+
        kmutex_t sc_intr_lock;
 
        const struct sunxi_nmi_config *sc_config;
@@ -177,22 +180,54 @@
     int (*func)(void *), void *arg, const char *xname)
 {
        struct sunxi_nmi_softc * const sc = device_private(dev);
-       u_int irq_type;
+       u_int irq_type, irq, pol;
        int ist;
 
-       /* 1st cell is the interrupt number */
-       const u_int irq = be32toh(specifier[0]);
-       /* 2nd cell is polarity */
-       const u_int pol = be32toh(specifier[1]);
+       if (sc->sc_intr_cells == 2) {
+               /* 1st cell is the interrupt number */
+               irq = be32toh(specifier[0]);
+               /* 2nd cell is polarity */
+               pol = be32toh(specifier[1]);
+       } else {
+               /* 1st cell is the GIC interrupt type and must be GIC_SPI */
+               if (be32toh(specifier[0]) != 0) {
+#ifdef DIAGNOSTIC
+                       device_printf(dev, "GIC intr type %u is invalid\n",
+                           be32toh(specifier[0]));
+#endif
+                       return NULL;
+               }
+               /* 2nd cell is the interrupt number */
+               irq = be32toh(specifier[1]);
+               /* 3rd cell is polarity */
+               pol = be32toh(specifier[2]);
+       }
 
-       if (irq != 0) {
+       if (sc->sc_intr_cells == 3 && irq != sc->sc_intr_nmi) {
+               /*
+                * Driver is requesting a wakeup irq, which we don't
+                * support today. Just pass it through to the parent
+                * interrupt controller.
+                */
+               const int ihandle = fdtbus_intr_parent(sc->sc_phandle);
+               if (ihandle == -1) {
+#ifdef DIAGNOSTIC
+                       device_printf(dev, "couldn't find interrupt parent\n");
+#endif
+                       return NULL;
+               }
+               return fdtbus_intr_establish_raw(ihandle, specifier, ipl,
+                   flags, func, arg, xname);
+       }
+
+       if (sc->sc_intr_cells == 2 && irq != 0) {
 #ifdef DIAGNOSTIC
                device_printf(dev, "IRQ %u is invalid\n", irq);
 #endif
                return NULL;
        }
 
-       switch (pol & 0x7) {
+       switch (pol & 0xf) {
        case 1: /* IRQ_TYPE_EDGE_RISING */
                irq_type = NMI_CTRL_IRQ_HIGH_EDGE;
                ist = IST_EDGE;
@@ -201,11 +236,11 @@
                irq_type = NMI_CTRL_IRQ_LOW_EDGE;
                ist = IST_EDGE;
                break;
-       case 3: /* IRQ_TYPE_LEVEL_HIGH */
+       case 4: /* IRQ_TYPE_LEVEL_HIGH */
                irq_type = NMI_CTRL_IRQ_HIGH_LEVEL;
                ist = IST_LEVEL;
                break;
-       case 4: /* IRQ_TYPE_LEVEL_LOW */
+       case 8: /* IRQ_TYPE_LEVEL_LOW */
                irq_type = NMI_CTRL_IRQ_LOW_LEVEL;
                ist = IST_LEVEL;
                break;
@@ -296,6 +331,18 @@
 {
        struct sunxi_nmi_softc * const sc = device_private(dev);
 
+       if (sc->sc_intr_cells == 3) {
+               const u_int irq = be32toh(specifier[1]);
+               if (irq != sc->sc_intr_nmi) {
+                       const int ihandle = fdtbus_intr_parent(sc->sc_phandle);
+                       if (ihandle == -1) {
+                               return false;
+                       }
+                       return fdtbus_intr_str_raw(ihandle, specifier, buf,
+                           buflen);
+               }
+       }
+
        snprintf(buf, buflen, "%s", sc->sc_config->name);
 
        return true;
@@ -323,9 +370,10 @@
        struct sunxi_nmi_softc * const sc = device_private(self);
        struct fdt_attach_args * const faa = aux;
        const int phandle = faa->faa_phandle;
+       const u_int *interrupts;
        bus_addr_t addr;
        bus_size_t size;
-       int error;
+       int error, len;
 
        if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
                aprint_error(": couldn't get registers\n");
@@ -341,8 +389,18 @@
                return;
        }
 
+       of_getprop_uint32(phandle, "#interrupt-cells", &sc->sc_intr_cells);
+       interrupts = fdtbus_get_prop(phandle, "interrupts", &len);
+       if (interrupts == NULL || len != 12 ||
+           be32toh(interrupts[0]) != 0 /* GIC_SPI */ ||
+           be32toh(interrupts[2]) != 4 /* IRQ_TYPE_LEVEL_HIGH */) {
+               aprint_error(": couldn't find GIC SPI for NMI\n");
+               return;
+       }
+       sc->sc_intr_nmi = be32toh(interrupts[1]);
+
        aprint_naive("\n");
-       aprint_normal(": %s\n", sc->sc_config->name);
+       aprint_normal(": %s, NMI IRQ %u\n", sc->sc_config->name, sc->sc_intr_nmi);
 
        mutex_init(&sc->sc_intr_lock, MUTEX_SPIN, IPL_HIGH);
 



Home | Main Index | Thread Index | Old Index