Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F146330569
D5030.id12716.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D5030.id12716.diff
View Options
Index: sys/arm/conf/ARMADA38X
===================================================================
--- sys/arm/conf/ARMADA38X
+++ sys/arm/conf/ARMADA38X
@@ -23,6 +23,7 @@
#options SCHED_4BSD # 4BSD scheduler
options SMP
+options ARM_INTRNG
# Debugging
#options DEBUG
Index: sys/arm/include/intr.h
===================================================================
--- sys/arm/include/intr.h
+++ sys/arm/include/intr.h
@@ -49,6 +49,11 @@
#define NIRQ 1024 /* XXX - It should be an option. */
#endif
+#if defined (SOC_MV_ARMADA38X)
+#define MSI_IRQ 0x3ff
+#define ERR_IRQ 0x3ff
+#endif
+
#ifdef notyet
#define INTR_SOLO INTR_MD1
typedef int intr_irq_filter_t(void *arg, struct trapframe *tf);
@@ -163,6 +168,9 @@
#define MSI_IRQ_NUM 32
#define MSI_IRQ (ERR_IRQ + ERR_IRQ_NUM)
#define NIRQ (MAIN_IRQ_NUM + ERR_IRQ_NUM + MSI_IRQ_NUM)
+#elif defined (SOC_MV_ARMADA38X)
+#define MSI_IRQ 0x3ff
+#define ERR_IRQ 0x3ff
#else
#define NIRQ 32
#endif
Index: sys/arm/mv/armada38x/files.armada38x
===================================================================
--- sys/arm/mv/armada38x/files.armada38x
+++ sys/arm/mv/armada38x/files.armada38x
@@ -1,4 +1,5 @@
# $FreeBSD$
+arm/mv/mpic.c standard
arm/mv/armada38x/armada38x.c standard
arm/mv/armada38x/armada38x_mp.c optional smp
Index: sys/arm/mv/mpic.c
===================================================================
--- sys/arm/mv/mpic.c
+++ sys/arm/mv/mpic.c
@@ -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>
@@ -53,6 +59,10 @@
#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)
@@ -71,35 +81,52 @@
#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 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_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, 1, RF_ACTIVE | RF_SHAREABLE },
+ { 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 +136,21 @@
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 +169,7 @@
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 +181,7 @@
{
struct mv_mpic_softc *sc;
int error;
+ uint32_t val;
sc = (struct mv_mpic_softc *)device_get_softc(dev);
@@ -151,11 +191,20 @@
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 +212,179 @@
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
+
+#ifdef SOC_MV_ARMADAXP
+ mpic_unmask_msi();
+#endif
+
+ 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 = get_pcpu()->pc_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);
+ 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);
}
+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);
+}
+
+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;
+
+ sc = device_get_softc(dev);
+
+ if (isrc->isrc_type == INTR_ISRCT_FDT)
+ error = mpic_map_fdt(sc, isrc, &irq);
+ else
+ 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 +396,10 @@
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 +428,42 @@
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 +478,42 @@
}
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 +547,7 @@
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 +594,8 @@
return (0);
}
-#if defined(SMP)
+
+#if defined(SMP) && defined(SOC_MV_ARMADAXP)
void
pic_ipi_send(cpuset_t cpus, u_int ipi)
{
Index: sys/arm/mv/mv_common.c
===================================================================
--- sys/arm/mv/mv_common.c
+++ sys/arm/mv/mv_common.c
@@ -2181,6 +2181,7 @@
{ NULL, NULL }
};
+#if !defined(ARM_INTRNG)
static int
fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
int *pol)
@@ -2204,6 +2205,7 @@
&fdt_pic_decode_ic,
NULL
};
+#endif
uint64_t
get_sar_value(void)
Index: sys/boot/fdt/dts/arm/db78460.dts
===================================================================
--- sys/boot/fdt/dts/arm/db78460.dts
+++ sys/boot/fdt/dts/arm/db78460.dts
@@ -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";
};
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Mar 2, 7:44 PM (3 h, 52 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29132155
Default Alt Text
D5030.id12716.diff (13 KB)
Attached To
Mode
D5030: Make MPIC compatible with ARM_INTRNG
Attached
Detach File
Event Timeline
Log In to Comment