Author: wma
Date: Mon Mar 14 07:05:41 2016
New Revision: 296825
URL: https://svnweb.freebsd.org/changeset/base/296825

Log:
  Make MPIC compatible with ARM_INTRNG
  
  After ARM_INTRNG introduction, MPIC code needed several modifications:
  - IRQ resource and its handler added
  -  several DEVMETHODs of INTRNG interface implemented
  -  defines enhanced to ensure code compiles as well for AXP as for A38X
  - added dummy MSI_IRQ, ERR_IRQ defines for Armada38x
  - MPIC driver was added to files.armada38x, ARM_INTRNG option enabled in
    kernconf file and regs of MPIC corrected in dts file.
  
  Instead of modifying Armada38X DTS, offsets to CPU registers defined in
  driver were changed. That required restoring 'reg' property of mpic node
  in ArmadaXP to state compliant with Linux DTS.
  
  Additionally, required ARM_INTRNG definitions were added to mv_common.c.
  
  Submitted by:          Bartosz Szczepanek <[email protected]>
  Obtained from:         Semihalf
  Sponsored by:          Stormshield
  Reviewed by:           adrian, andrew, ian, skra
  Approved by:           cognet (mentor)
  Differential Revision: https://reviews.freebsd.org/D5030

Modified:
  head/sys/arm/conf/ARMADA38X
  head/sys/arm/mv/armada38x/files.armada38x
  head/sys/arm/mv/mpic.c
  head/sys/arm/mv/mvreg.h
  head/sys/boot/fdt/dts/arm/db78460.dts

Modified: head/sys/arm/conf/ARMADA38X
==============================================================================
--- head/sys/arm/conf/ARMADA38X Mon Mar 14 06:30:37 2016        (r296824)
+++ head/sys/arm/conf/ARMADA38X Mon Mar 14 07:05:41 2016        (r296825)
@@ -23,6 +23,7 @@ options       SCHED_ULE               # ULE scheduler
 #options       SCHED_4BSD              # 4BSD scheduler
 
 options        SMP
+options        ARM_INTRNG
 
 # Debugging
 #options       DEBUG

Modified: head/sys/arm/mv/armada38x/files.armada38x
==============================================================================
--- head/sys/arm/mv/armada38x/files.armada38x   Mon Mar 14 06:30:37 2016        
(r296824)
+++ head/sys/arm/mv/armada38x/files.armada38x   Mon Mar 14 07:05:41 2016        
(r296825)
@@ -1,4 +1,5 @@
 # $FreeBSD$
+arm/mv/mpic.c                  standard
 
 arm/mv/armada38x/armada38x.c   standard
 arm/mv/armada38x/armada38x_mp.c        optional smp

Modified: head/sys/arm/mv/mpic.c
==============================================================================
--- head/sys/arm/mv/mpic.c      Mon Mar 14 06:30:37 2016        (r296824)
+++ head/sys/arm/mv/mpic.c      Mon Mar 14 07:05:41 2016        (r296825)
@@ -33,14 +33,20 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include "opt_platform.h"
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/bus.h>
 #include <sys/kernel.h>
 #include <sys/cpuset.h>
 #include <sys/ktr.h>
+#include <sys/kdb.h>
 #include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
 #include <sys/rman.h>
+#include <sys/proc.h>
 
 #include <machine/bus.h>
 #include <machine/intr.h>
@@ -48,11 +54,16 @@ __FBSDID("$FreeBSD$");
 #include <machine/smp.h>
 
 #include <arm/mv/mvvar.h>
+#include <arm/mv/mvreg.h>
 
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
 #include <dev/fdt/fdt_common.h>
 
+#ifdef ARM_INTRNG
+#include "pic_if.h"
+#endif
+
 #ifdef DEBUG
 #define debugf(fmt, args...) do { printf("%s(): ", __func__);  \
     printf(fmt,##args); } while (0)
@@ -60,46 +71,63 @@ __FBSDID("$FreeBSD$");
 #define debugf(fmt, args...)
 #endif
 
-#define MPIC_INT_ERR                   4
-#define MPIC_INT_MSI                   96
+#define        MPIC_INT_ERR                    4
+#define        MPIC_INT_MSI                    96
 
-#define IRQ_MASK               0x3ff
+#define        IRQ_MASK                0x3ff
 
-#define MPIC_CTRL              0x0
-#define MPIC_SOFT_INT          0x4
-#define MPIC_SOFT_INT_DRBL1    (1 << 5)
-#define MPIC_ERR_CAUSE         0x20
-#define MPIC_ISE               0x30
-#define MPIC_ICE               0x34
-
-
-#define MPIC_IN_DRBL           0x78
-#define MPIC_IN_DRBL_MASK      0x7c
-#define MPIC_CTP               0xb0
-#define MPIC_CTP               0xb0
-#define MPIC_IIACK             0xb4
-#define MPIC_ISM               0xb8
-#define MPIC_ICM               0xbc
-#define MPIC_ERR_MASK          0xec0
+#define        MPIC_CTRL               0x0
+#define        MPIC_SOFT_INT           0x4
+#define        MPIC_SOFT_INT_DRBL1     (1 << 5)
+#define        MPIC_ERR_CAUSE          0x20
+#define        MPIC_ISE                0x30
+#define        MPIC_ICE                0x34
+#define        MPIC_INT_CTL(irq)       (0x100 + (irq)*4)
+
+#define        MPIC_INT_IRQ_FIQ_MASK(cpuid)    (0x101 << (cpuid))
+#define        MPIC_CTRL_NIRQS(ctrl)   (((ctrl) >> 2) & 0x3ff)
+
+#define        MPIC_IN_DRBL            0x08
+#define        MPIC_IN_DRBL_MASK       0x0c
+#define        MPIC_PPI_CAUSE          0x10
+#define        MPIC_CTP                0x40
+#define        MPIC_IIACK              0x44
+#define        MPIC_ISM                0x48
+#define        MPIC_ICM                0x4c
+#define        MPIC_ERR_MASK           0xe50
+
+#define        MPIC_PPI        32
 
 struct mv_mpic_softc {
        device_t                sc_dev;
-       struct resource *       mpic_res[3];
+       struct resource *       mpic_res[4];
        bus_space_tag_t         mpic_bst;
        bus_space_handle_t      mpic_bsh;
        bus_space_tag_t         cpu_bst;
        bus_space_handle_t      cpu_bsh;
        bus_space_tag_t         drbl_bst;
        bus_space_handle_t      drbl_bsh;
+       struct mtx              mtx;
+
+       struct intr_irqsrc **   mpic_isrcs;
+       int                     nirqs;
+       void *                  intr_hand;
 };
 
 static struct resource_spec mv_mpic_spec[] = {
        { SYS_RES_MEMORY,       0,      RF_ACTIVE },
        { SYS_RES_MEMORY,       1,      RF_ACTIVE },
-       { SYS_RES_MEMORY,       2,      RF_ACTIVE },
+       { SYS_RES_MEMORY,       2,      RF_ACTIVE | RF_OPTIONAL },
+       { SYS_RES_IRQ,          0,      RF_ACTIVE | RF_OPTIONAL },
        { -1, 0 }
 };
 
+static struct ofw_compat_data compat_data[] = {
+       {"mrvl,mpic",           true},
+       {"marvell,mpic",        true},
+       {NULL,                  false}
+};
+
 static struct mv_mpic_softc *mv_mpic_sc = NULL;
 
 void mpic_send_ipi(int cpus, u_int ipi);
@@ -109,9 +137,21 @@ static int mv_mpic_attach(device_t);
 uint32_t       mv_mpic_get_cause(void);
 uint32_t       mv_mpic_get_cause_err(void);
 uint32_t       mv_mpic_get_msi(void);
+static void    mpic_unmask_irq(uintptr_t nb);
+static void    mpic_mask_irq(uintptr_t nb);
+static void    mpic_mask_irq_err(uintptr_t nb);
+static void    mpic_unmask_irq_err(uintptr_t nb);
+static int     mpic_intr(void *arg);
+static void    mpic_unmask_msi(void);
+#ifndef ARM_INTRNG
 static void    arm_mask_irq_err(uintptr_t);
 static void    arm_unmask_irq_err(uintptr_t);
-static void    arm_unmask_msi(void);
+#endif
+
+#define        MPIC_WRITE(softc, reg, val) \
+    bus_space_write_4((softc)->mpic_bst, (softc)->mpic_bsh, (reg), (val))
+#define        MPIC_READ(softc, reg) \
+    bus_space_read_4((softc)->mpic_bst, (softc)->mpic_bsh, (reg))
 
 #define MPIC_CPU_WRITE(softc, reg, val) \
     bus_space_write_4((softc)->cpu_bst, (softc)->cpu_bsh, (reg), (val))
@@ -130,7 +170,7 @@ mv_mpic_probe(device_t dev)
        if (!ofw_bus_status_okay(dev))
                return (ENXIO);
 
-       if (!ofw_bus_is_compatible(dev, "mrvl,mpic"))
+       if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
                return (ENXIO);
 
        device_set_desc(dev, "Marvell Integrated Interrupt Controller");
@@ -142,6 +182,7 @@ mv_mpic_attach(device_t dev)
 {
        struct mv_mpic_softc *sc;
        int error;
+       uint32_t val;
 
        sc = (struct mv_mpic_softc *)device_get_softc(dev);
 
@@ -151,11 +192,20 @@ mv_mpic_attach(device_t dev)
 
        sc->sc_dev = dev;
 
+       mtx_init(&sc->mtx, "MPIC lock", NULL, MTX_SPIN);
+
        error = bus_alloc_resources(dev, mv_mpic_spec, sc->mpic_res);
        if (error) {
                device_printf(dev, "could not allocate resources\n");
                return (ENXIO);
        }
+#ifdef ARM_INTRNG
+       if (sc->mpic_res[3] == NULL)
+               device_printf(dev, "No interrupt to use.\n");
+       else
+               bus_setup_intr(dev, sc->mpic_res[3], INTR_TYPE_CLK,
+                   mpic_intr, NULL, sc, &sc->intr_hand);
+#endif
 
        sc->mpic_bst = rman_get_bustag(sc->mpic_res[0]);
        sc->mpic_bsh = rman_get_bushandle(sc->mpic_res[0]);
@@ -163,21 +213,182 @@ mv_mpic_attach(device_t dev)
        sc->cpu_bst = rman_get_bustag(sc->mpic_res[1]);
        sc->cpu_bsh = rman_get_bushandle(sc->mpic_res[1]);
 
-       sc->drbl_bst = rman_get_bustag(sc->mpic_res[2]);
-       sc->drbl_bsh = rman_get_bushandle(sc->mpic_res[2]);
+       if (sc->mpic_res[2] != NULL) {
+               /* This is required only if MSIs are used. */
+               sc->drbl_bst = rman_get_bustag(sc->mpic_res[2]);
+               sc->drbl_bsh = rman_get_bushandle(sc->mpic_res[2]);
+       }
 
        bus_space_write_4(mv_mpic_sc->mpic_bst, mv_mpic_sc->mpic_bsh,
            MPIC_CTRL, 1);
        MPIC_CPU_WRITE(mv_mpic_sc, MPIC_CTP, 0);
 
-       arm_unmask_msi();
+       val = MPIC_READ(mv_mpic_sc, MPIC_CTRL);
+       sc->nirqs = MPIC_CTRL_NIRQS(val);
+
+#ifdef ARM_INTRNG
+       sc->mpic_isrcs = malloc(sc->nirqs * sizeof (*sc->mpic_isrcs), M_DEVBUF,
+           M_WAITOK | M_ZERO);
+
+       if (intr_pic_register(dev, OF_xref_from_device(dev)) != 0) {
+               device_printf(dev, "could not register PIC\n");
+               bus_release_resources(dev, mv_mpic_spec, sc->mpic_res);
+               return (ENXIO);
+       }
+#endif
+
+       mpic_unmask_msi();
 
        return (0);
 }
 
+#ifdef ARM_INTRNG
+static int
+mpic_intr(void *arg)
+{
+       struct mv_mpic_softc *sc;
+       struct trapframe *tf;
+       struct intr_irqsrc *isrc;
+       uint32_t cause, irqsrc;
+       unsigned int irq;
+       u_int cpuid;
+
+       sc = arg;
+       tf = curthread->td_intr_frame;
+       cpuid = PCPU_GET(cpuid);
+       irq = 0;
+
+       for (cause = MPIC_CPU_READ(sc, MPIC_PPI_CAUSE); cause > 0;
+           cause >>= 1, irq++) {
+               if (cause & 1) {
+                       irqsrc = MPIC_READ(sc, MPIC_INT_CTL(irq));
+                       if ((irqsrc & MPIC_INT_IRQ_FIQ_MASK(cpuid)) == 0)
+                               continue;
+                       isrc = sc->mpic_isrcs[irq];
+                       if (isrc == NULL) {
+                               device_printf(sc->sc_dev, "Stray interrupt %u 
detected\n", irq);
+                               mpic_mask_irq(irq);
+                               continue;
+                       }
+                       intr_irq_dispatch(isrc, tf);
+               }
+       }
+
+       return (FILTER_HANDLED);
+}
+
+static int
+mpic_attach_isrc(struct mv_mpic_softc *sc, struct intr_irqsrc *isrc, u_int irq)
+{
+       const char *name;
+
+       mtx_lock_spin(&sc->mtx);
+       if (sc->mpic_isrcs[irq] != NULL) {
+               mtx_unlock_spin(&sc->mtx);
+               return (sc->mpic_isrcs[irq] == isrc ? 0 : EEXIST);
+       }
+       sc->mpic_isrcs[irq] = isrc;
+       isrc->isrc_data = irq;
+       mtx_unlock_spin(&sc->mtx);
+
+       name = device_get_nameunit(sc->sc_dev);
+       intr_irq_set_name(isrc, "%s", name);
+
+       return (0);
+}
+
+#ifdef FDT
+static int
+mpic_map_fdt(struct mv_mpic_softc *sc, struct intr_irqsrc *isrc, u_int *irqp)
+{
+       u_int irq;
+       int error;
+
+       if (isrc->isrc_ncells != 1)
+               return (EINVAL);
+
+       irq = isrc->isrc_cells[0];
+
+       error = mpic_attach_isrc(sc, isrc, irq);
+       if (error != 0)
+               return (error);
+
+       isrc->isrc_nspc_num = irq;
+       isrc->isrc_trig = INTR_TRIGGER_CONFORM;
+       isrc->isrc_pol = INTR_POLARITY_CONFORM;
+       isrc->isrc_nspc_type = INTR_IRQ_NSPC_PLAIN;
+
+       *irqp = irq;
+
+       return (0);
+}
+#endif
+
+static int
+mpic_register(device_t dev, struct intr_irqsrc *isrc, boolean_t *is_percpu)
+{
+       struct mv_mpic_softc *sc;
+       int error;
+       u_int irq = 0;
+
+       sc = device_get_softc(dev);
+
+#ifdef FDT
+       if (isrc->isrc_type == INTR_ISRCT_FDT)
+               error = mpic_map_fdt(sc, isrc, &irq);
+       else
+#endif
+               error = EINVAL;
+
+       if (error == 0)
+               *is_percpu = irq < MPIC_PPI;
+
+       return (error);
+}
+
+static void
+mpic_disable_source(device_t dev, struct intr_irqsrc *isrc)
+{
+       u_int irq;
+
+       irq = isrc->isrc_data;
+       mpic_mask_irq(irq);
+}
+
+static void
+mpic_enable_source(device_t dev, struct intr_irqsrc *isrc)
+{
+       u_int irq;
+
+       irq = isrc->isrc_data;
+       mpic_unmask_irq(irq);
+}
+static void
+mpic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+
+       mpic_disable_source(dev, isrc);
+}
+
+static void
+mpic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+
+       mpic_enable_source(dev, isrc);
+}
+#endif
+
 static device_method_t mv_mpic_methods[] = {
        DEVMETHOD(device_probe,         mv_mpic_probe),
        DEVMETHOD(device_attach,        mv_mpic_attach),
+
+#ifdef ARM_INTRNG
+       DEVMETHOD(pic_register,         mpic_register),
+       DEVMETHOD(pic_disable_source,   mpic_disable_source),
+       DEVMETHOD(pic_enable_source,    mpic_enable_source),
+       DEVMETHOD(pic_post_ithread,     mpic_post_ithread),
+       DEVMETHOD(pic_pre_ithread,      mpic_pre_ithread),
+#endif
        { 0, 0 }
 };
 
@@ -189,8 +400,10 @@ static driver_t mv_mpic_driver = {
 
 static devclass_t mv_mpic_devclass;
 
-DRIVER_MODULE(mpic, simplebus, mv_mpic_driver, mv_mpic_devclass, 0, 0);
+EARLY_DRIVER_MODULE(mpic, simplebus, mv_mpic_driver, mv_mpic_devclass, 0, 0,
+    BUS_PASS_INTERRUPT);
 
+#ifndef ARM_INTRNG
 int
 arm_get_next_irq(int last)
 {
@@ -219,49 +432,42 @@ void
 arm_mask_irq(uintptr_t nb)
 {
 
-       MPIC_CPU_WRITE(mv_mpic_sc, MPIC_CTP, 1);
-
-       if (nb < ERR_IRQ) {
-               bus_space_write_4(mv_mpic_sc->mpic_bst, mv_mpic_sc->mpic_bsh,
-                   MPIC_ICE, nb);
-               MPIC_CPU_WRITE(mv_mpic_sc, MPIC_ISM, nb);
-       } else if (nb < MSI_IRQ)
-               arm_mask_irq_err(nb);
+       mpic_mask_irq(nb);
 }
 
 
 static void
 arm_mask_irq_err(uintptr_t nb)
 {
-       uint32_t mask;
-       uint8_t bit_off;
 
-       bit_off = nb - ERR_IRQ;
-       mask = MPIC_CPU_READ(mv_mpic_sc, MPIC_ERR_MASK);
-       mask &= ~(1 << bit_off);
-       MPIC_CPU_WRITE(mv_mpic_sc, MPIC_ERR_MASK, mask);
+       mpic_mask_irq_err(nb);
 }
 
 void
 arm_unmask_irq(uintptr_t nb)
 {
 
-       MPIC_CPU_WRITE(mv_mpic_sc, MPIC_CTP, 0);
-
-       if (nb < ERR_IRQ) {
-               bus_space_write_4(mv_mpic_sc->mpic_bst, mv_mpic_sc->mpic_bsh,
-                   MPIC_ISE, nb);
-               MPIC_CPU_WRITE(mv_mpic_sc, MPIC_ICM, nb);
-       } else if (nb < MSI_IRQ)
-               arm_unmask_irq_err(nb);
-
-       if (nb == 0)
-               MPIC_CPU_WRITE(mv_mpic_sc, MPIC_IN_DRBL_MASK, 0xffffffff);
+       mpic_unmask_irq(nb);
 }
 
 void
 arm_unmask_irq_err(uintptr_t nb)
 {
+
+       mpic_unmask_irq_err(nb);
+}
+#endif
+
+static void
+mpic_unmask_msi(void)
+{
+
+       mpic_unmask_irq(MPIC_INT_MSI);
+}
+
+static void
+mpic_unmask_irq_err(uintptr_t nb)
+{
        uint32_t mask;
        uint8_t bit_off;
 
@@ -276,10 +482,42 @@ arm_unmask_irq_err(uintptr_t nb)
 }
 
 static void
-arm_unmask_msi(void)
+mpic_mask_irq_err(uintptr_t nb)
+{
+       uint32_t mask;
+       uint8_t bit_off;
+
+       bit_off = nb - ERR_IRQ;
+       mask = MPIC_CPU_READ(mv_mpic_sc, MPIC_ERR_MASK);
+       mask &= ~(1 << bit_off);
+       MPIC_CPU_WRITE(mv_mpic_sc, MPIC_ERR_MASK, mask);
+}
+
+static void
+mpic_unmask_irq(uintptr_t nb)
+{
+
+       if (nb < ERR_IRQ) {
+               bus_space_write_4(mv_mpic_sc->mpic_bst, mv_mpic_sc->mpic_bsh,
+                   MPIC_ISE, nb);
+               MPIC_CPU_WRITE(mv_mpic_sc, MPIC_ICM, nb);
+       } else if (nb < MSI_IRQ)
+               mpic_unmask_irq_err(nb);
+
+       if (nb == 0)
+               MPIC_CPU_WRITE(mv_mpic_sc, MPIC_IN_DRBL_MASK, 0xffffffff);
+}
+
+static void
+mpic_mask_irq(uintptr_t nb)
 {
 
-       arm_unmask_irq(MPIC_INT_MSI);
+       if (nb < ERR_IRQ) {
+               bus_space_write_4(mv_mpic_sc->mpic_bst, mv_mpic_sc->mpic_bsh,
+                   MPIC_ICE, nb);
+               MPIC_CPU_WRITE(mv_mpic_sc, MPIC_ISM, nb);
+       } else if (nb < MSI_IRQ)
+               mpic_mask_irq_err(nb);
 }
 
 uint32_t
@@ -313,6 +551,7 @@ mv_mpic_get_msi(void)
        uint32_t cause;
        uint8_t bit_off;
 
+       KASSERT(mv_mpic_sc->drbl_bst != NULL, ("No doorbell in 
mv_mpic_get_msi"));
        cause = MPIC_DRBL_READ(mv_mpic_sc, 0);
 
        if (cause)
@@ -359,7 +598,8 @@ mv_msi_data(int irq, uint64_t *addr, uin
        return (0);
 }
 
-#if defined(SMP)
+
+#if defined(SMP) && defined(SOC_MV_ARMADAXP)
 void
 intr_pic_init_secondary(void)
 {

Modified: head/sys/arm/mv/mvreg.h
==============================================================================
--- head/sys/arm/mv/mvreg.h     Mon Mar 14 06:30:37 2016        (r296824)
+++ head/sys/arm/mv/mvreg.h     Mon Mar 14 07:05:41 2016        (r296825)
@@ -67,7 +67,10 @@
 #elif defined (SOC_MV_ARMADAXP)
 #define IRQ_CAUSE              0x18
 #define IRQ_MASK               0x30
-#else /* !SOC_MV_DISCOVERY && !SOC_MV_LOKIPLUS */
+#elif defined (SOC_MV_ARMADA38X)
+#define        MSI_IRQ                 0x3ff
+#define        ERR_IRQ                 0x3ff
+#else
 #define IRQ_CAUSE              0x0
 #define IRQ_MASK               0x4
 #define FIQ_MASK               0x8

Modified: head/sys/boot/fdt/dts/arm/db78460.dts
==============================================================================
--- head/sys/boot/fdt/dts/arm/db78460.dts       Mon Mar 14 06:30:37 2016        
(r296824)
+++ head/sys/boot/fdt/dts/arm/db78460.dts       Mon Mar 14 07:05:41 2016        
(r296825)
@@ -75,7 +75,7 @@
                        interrupt-controller;
                        #address-cells = <0>;
                        #interrupt-cells = <1>;
-                       reg = <0x20a00 0x500 0x21000 0x800 0x20400 0x100>;
+                       reg = <0x20a00 0x500 0x21870 0x58 0x20400 0x100>;
                        compatible = "mrvl,mpic";
                };
 
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to