mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
Adda new common GIC header to handle the common parts of the GICv2 and
GICv3 drivers. For now it just contains common distributor registers. Obtained from: ABT Systems Ltd Sponsored by: The FreeBSD Foundation
This commit is contained in:
parent
3cbaf64f2e
commit
4d7d72fb23
2 changed files with 102 additions and 47 deletions
|
|
@ -67,6 +67,7 @@ __FBSDID("$FreeBSD$");
|
|||
#endif
|
||||
|
||||
#include <arm/arm/gic.h>
|
||||
#include <arm/arm/gic_common.h>
|
||||
|
||||
#ifdef INTRNG
|
||||
#include "pic_if.h"
|
||||
|
|
@ -76,20 +77,6 @@ __FBSDID("$FreeBSD$");
|
|||
/* We are using GICv2 register naming */
|
||||
|
||||
/* Distributor Registers */
|
||||
#define GICD_CTLR 0x000 /* v1 ICDDCR */
|
||||
#define GICD_TYPER 0x004 /* v1 ICDICTR */
|
||||
#define GICD_IIDR 0x008 /* v1 ICDIIDR */
|
||||
#define GICD_IGROUPR(n) (0x0080 + ((n) * 4)) /* v1 ICDISER */
|
||||
#define GICD_ISENABLER(n) (0x0100 + ((n) * 4)) /* v1 ICDISER */
|
||||
#define GICD_ICENABLER(n) (0x0180 + ((n) * 4)) /* v1 ICDICER */
|
||||
#define GICD_ISPENDR(n) (0x0200 + ((n) * 4)) /* v1 ICDISPR */
|
||||
#define GICD_ICPENDR(n) (0x0280 + ((n) * 4)) /* v1 ICDICPR */
|
||||
#define GICD_ICACTIVER(n) (0x0380 + ((n) * 4)) /* v1 ICDABR */
|
||||
#define GICD_IPRIORITYR(n) (0x0400 + ((n) * 4)) /* v1 ICDIPR */
|
||||
#define GICD_ITARGETSR(n) (0x0800 + ((n) * 4)) /* v1 ICDIPTR */
|
||||
#define GICD_ICFGR(n) (0x0C00 + ((n) * 4)) /* v1 ICDICFR */
|
||||
#define GICD_SGIR(n) (0x0F00 + ((n) * 4)) /* v1 ICDSGIR */
|
||||
#define GICD_SGI_TARGET_SHIFT 16
|
||||
|
||||
/* CPU Registers */
|
||||
#define GICC_CTLR 0x0000 /* v1 ICCICR */
|
||||
|
|
@ -107,14 +94,6 @@ __FBSDID("$FreeBSD$");
|
|||
#define GIC_SUPPORT_SECEXT(_sc) \
|
||||
((_sc->typer & GICD_TYPER_SECURITYEXT) == GICD_TYPER_SECURITYEXT)
|
||||
|
||||
/* First bit is a polarity bit (0 - low, 1 - high) */
|
||||
#define GICD_ICFGR_POL_LOW (0 << 0)
|
||||
#define GICD_ICFGR_POL_HIGH (1 << 0)
|
||||
#define GICD_ICFGR_POL_MASK 0x1
|
||||
/* Second bit is a trigger bit (0 - level, 1 - edge) */
|
||||
#define GICD_ICFGR_TRIG_LVL (0 << 1)
|
||||
#define GICD_ICFGR_TRIG_EDGE (1 << 1)
|
||||
#define GICD_ICFGR_TRIG_MASK 0x2
|
||||
|
||||
#ifndef GIC_DEFAULT_ICFGR_INIT
|
||||
#define GIC_DEFAULT_ICFGR_INIT 0x00000000
|
||||
|
|
@ -192,14 +171,14 @@ static inline void
|
|||
gic_irq_unmask(struct arm_gic_softc *sc, u_int irq)
|
||||
{
|
||||
|
||||
gic_d_write_4(sc, GICD_ISENABLER(irq >> 5), (1UL << (irq & 0x1F)));
|
||||
gic_d_write_4(sc, GICD_ISENABLER(irq), (1UL << (irq & 0x1F)));
|
||||
}
|
||||
|
||||
static inline void
|
||||
gic_irq_mask(struct arm_gic_softc *sc, u_int irq)
|
||||
{
|
||||
|
||||
gic_d_write_4(sc, GICD_ICENABLER(irq >> 5), (1UL << (irq & 0x1F)));
|
||||
gic_d_write_4(sc, GICD_ICENABLER(irq), (1UL << (irq & 0x1F)));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -239,11 +218,11 @@ arm_gic_init_secondary(device_t dev)
|
|||
arm_gic_map[cpu] = gic_cpu_mask(sc);
|
||||
|
||||
for (irq = 0; irq < sc->nirqs; irq += 4)
|
||||
gic_d_write_4(sc, GICD_IPRIORITYR(irq >> 2), 0);
|
||||
gic_d_write_4(sc, GICD_IPRIORITYR(irq), 0);
|
||||
|
||||
/* Set all the interrupts to be in Group 0 (secure) */
|
||||
for (irq = 0; GIC_SUPPORT_SECEXT(sc) && irq < sc->nirqs; irq += 32) {
|
||||
gic_d_write_4(sc, GICD_IGROUPR(irq >> 5), 0);
|
||||
gic_d_write_4(sc, GICD_IGROUPR(irq), 0);
|
||||
}
|
||||
|
||||
/* Enable CPU interface */
|
||||
|
|
@ -276,11 +255,11 @@ arm_gic_init_secondary(device_t dev)
|
|||
arm_gic_map[PCPU_GET(cpuid)] = gic_cpu_mask(sc);
|
||||
|
||||
for (i = 0; i < sc->nirqs; i += 4)
|
||||
gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0);
|
||||
gic_d_write_4(sc, GICD_IPRIORITYR(i), 0);
|
||||
|
||||
/* Set all the interrupts to be in Group 0 (secure) */
|
||||
for (i = 0; GIC_SUPPORT_SECEXT(sc) && i < sc->nirqs; i += 32) {
|
||||
gic_d_write_4(sc, GICD_IGROUPR(i >> 5), 0);
|
||||
gic_d_write_4(sc, GICD_IGROUPR(i), 0);
|
||||
}
|
||||
|
||||
/* Enable CPU interface */
|
||||
|
|
@ -295,9 +274,9 @@ arm_gic_init_secondary(device_t dev)
|
|||
/*
|
||||
* Activate the timer interrupts: virtual, secure, and non-secure.
|
||||
*/
|
||||
gic_d_write_4(sc, GICD_ISENABLER(27 >> 5), (1UL << (27 & 0x1F)));
|
||||
gic_d_write_4(sc, GICD_ISENABLER(29 >> 5), (1UL << (29 & 0x1F)));
|
||||
gic_d_write_4(sc, GICD_ISENABLER(30 >> 5), (1UL << (30 & 0x1F)));
|
||||
gic_d_write_4(sc, GICD_ISENABLER(27), (1UL << (27 & 0x1F)));
|
||||
gic_d_write_4(sc, GICD_ISENABLER(29), (1UL << (29 & 0x1F)));
|
||||
gic_d_write_4(sc, GICD_ISENABLER(30), (1UL << (30 & 0x1F)));
|
||||
}
|
||||
#endif /* INTRNG */
|
||||
#endif /* SMP */
|
||||
|
|
@ -484,18 +463,19 @@ arm_gic_attach(device_t dev)
|
|||
#endif
|
||||
|
||||
icciidr = gic_c_read_4(sc, GICC_IIDR);
|
||||
device_printf(dev,"pn 0x%x, arch 0x%x, rev 0x%x, implementer 0x%x irqs %u\n",
|
||||
icciidr>>20, (icciidr>>16) & 0xF, (icciidr>>12) & 0xf,
|
||||
(icciidr & 0xfff), sc->nirqs);
|
||||
device_printf(dev,
|
||||
"pn 0x%x, arch 0x%x, rev 0x%x, implementer 0x%x irqs %u\n",
|
||||
GICD_IIDR_PROD(icciidr), GICD_IIDR_VAR(icciidr),
|
||||
GICD_IIDR_REV(icciidr), GICD_IIDR_IMPL(icciidr), sc->nirqs);
|
||||
|
||||
/* Set all global interrupts to be level triggered, active low. */
|
||||
for (i = 32; i < sc->nirqs; i += 16) {
|
||||
gic_d_write_4(sc, GICD_ICFGR(i >> 4), GIC_DEFAULT_ICFGR_INIT);
|
||||
gic_d_write_4(sc, GICD_ICFGR(i), GIC_DEFAULT_ICFGR_INIT);
|
||||
}
|
||||
|
||||
/* Disable all interrupts. */
|
||||
for (i = 32; i < sc->nirqs; i += 32) {
|
||||
gic_d_write_4(sc, GICD_ICENABLER(i >> 5), 0xFFFFFFFF);
|
||||
gic_d_write_4(sc, GICD_ICENABLER(i), 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
/* Find the current cpu mask */
|
||||
|
|
@ -507,15 +487,15 @@ arm_gic_attach(device_t dev)
|
|||
mask |= mask << 16;
|
||||
|
||||
for (i = 0; i < sc->nirqs; i += 4) {
|
||||
gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0);
|
||||
gic_d_write_4(sc, GICD_IPRIORITYR(i), 0);
|
||||
if (i > 32) {
|
||||
gic_d_write_4(sc, GICD_ITARGETSR(i >> 2), mask);
|
||||
gic_d_write_4(sc, GICD_ITARGETSR(i), mask);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set all the interrupts to be in Group 0 (secure) */
|
||||
for (i = 0; GIC_SUPPORT_SECEXT(sc) && i < sc->nirqs; i += 32) {
|
||||
gic_d_write_4(sc, GICD_IGROUPR(i >> 5), 0);
|
||||
gic_d_write_4(sc, GICD_IGROUPR(i), 0);
|
||||
}
|
||||
|
||||
/* Enable CPU interface */
|
||||
|
|
@ -725,7 +705,7 @@ gic_config(struct arm_gic_softc *sc, u_int irq, enum intr_trigger trig,
|
|||
|
||||
mtx_lock_spin(&sc->mutex);
|
||||
|
||||
reg = gic_d_read_4(sc, GICD_ICFGR(irq >> 4));
|
||||
reg = gic_d_read_4(sc, GICD_ICFGR(irq));
|
||||
mask = (reg >> 2*(irq % 16)) & 0x3;
|
||||
|
||||
if (pol == INTR_POLARITY_LOW) {
|
||||
|
|
@ -747,7 +727,7 @@ gic_config(struct arm_gic_softc *sc, u_int irq, enum intr_trigger trig,
|
|||
/* Set mask */
|
||||
reg = reg & ~(0x3 << 2*(irq % 16));
|
||||
reg = reg | (mask << 2*(irq % 16));
|
||||
gic_d_write_4(sc, GICD_ICFGR(irq >> 4), reg);
|
||||
gic_d_write_4(sc, GICD_ICFGR(irq), reg);
|
||||
|
||||
mtx_unlock_spin(&sc->mutex);
|
||||
}
|
||||
|
|
@ -1089,7 +1069,7 @@ arm_gic_ipi_send(device_t dev, struct intr_irqsrc *isrc, cpuset_t cpus,
|
|||
if (CPU_ISSET(i, &cpus))
|
||||
val |= arm_gic_map[i] << GICD_SGI_TARGET_SHIFT;
|
||||
|
||||
gic_d_write_4(sc, GICD_SGIR(0), val | gi->gi_irq);
|
||||
gic_d_write_4(sc, GICD_SGIR, val | gi->gi_irq);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -1157,7 +1137,7 @@ arm_gic_config(device_t dev, int irq, enum intr_trigger trig,
|
|||
|
||||
mtx_lock_spin(&sc->mutex);
|
||||
|
||||
reg = gic_d_read_4(sc, GICD_ICFGR(irq >> 4));
|
||||
reg = gic_d_read_4(sc, GICD_ICFGR(irq));
|
||||
mask = (reg >> 2*(irq % 16)) & 0x3;
|
||||
|
||||
if (pol == INTR_POLARITY_LOW) {
|
||||
|
|
@ -1179,7 +1159,7 @@ arm_gic_config(device_t dev, int irq, enum intr_trigger trig,
|
|||
/* Set mask */
|
||||
reg = reg & ~(0x3 << 2*(irq % 16));
|
||||
reg = reg | (mask << 2*(irq % 16));
|
||||
gic_d_write_4(sc, GICD_ICFGR(irq >> 4), reg);
|
||||
gic_d_write_4(sc, GICD_ICFGR(irq), reg);
|
||||
|
||||
mtx_unlock_spin(&sc->mutex);
|
||||
|
||||
|
|
@ -1196,7 +1176,7 @@ arm_gic_mask(device_t dev, int irq)
|
|||
{
|
||||
struct arm_gic_softc *sc = device_get_softc(dev);
|
||||
|
||||
gic_d_write_4(sc, GICD_ICENABLER(irq >> 5), (1UL << (irq & 0x1F)));
|
||||
gic_d_write_4(sc, GICD_ICENABLER(irq), (1UL << (irq & 0x1F)));
|
||||
gic_c_write_4(sc, GICC_EOIR, irq); /* XXX - not allowed */
|
||||
}
|
||||
|
||||
|
|
@ -1208,7 +1188,7 @@ arm_gic_unmask(device_t dev, int irq)
|
|||
if (irq > GIC_LAST_SGI)
|
||||
arm_irq_memory_barrier(irq);
|
||||
|
||||
gic_d_write_4(sc, GICD_ISENABLER(irq >> 5), (1UL << (irq & 0x1F)));
|
||||
gic_d_write_4(sc, GICD_ISENABLER(irq), (1UL << (irq & 0x1F)));
|
||||
}
|
||||
|
||||
#ifdef SMP
|
||||
|
|
@ -1222,7 +1202,7 @@ arm_gic_ipi_send(device_t dev, cpuset_t cpus, u_int ipi)
|
|||
if (CPU_ISSET(i, &cpus))
|
||||
val |= arm_gic_map[i] << GICD_SGI_TARGET_SHIFT;
|
||||
|
||||
gic_d_write_4(sc, GICD_SGIR(0), val | ipi);
|
||||
gic_d_write_4(sc, GICD_SGIR, val | ipi);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
|||
75
sys/arm/arm/gic_common.h
Normal file
75
sys/arm/arm/gic_common.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*-
|
||||
* Copyright (c) 2016 The FreeBSD Foundation
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by Andrew Turner under
|
||||
* the sponsorship of the FreeBSD Foundation.
|
||||
*
|
||||
* 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _GIC_COMMON_H_
|
||||
#define _GIC_COMMON_H_
|
||||
|
||||
/* Common register values */
|
||||
#define GICD_CTLR 0x0000 /* v1 ICDDCR */
|
||||
#define GICD_TYPER 0x0004 /* v1 ICDICTR */
|
||||
#define GICD_IIDR 0x0008 /* v1 ICDIIDR */
|
||||
#define GICD_IIDR_PROD_SHIFT 24
|
||||
#define GICD_IIDR_PROD_MASK 0xff000000
|
||||
#define GICD_IIDR_PROD(x) \
|
||||
(((x) & GICD_IIDR_PROD_MASK) >> GICD_IIDR_PROD_SHIFT)
|
||||
#define GICD_IIDR_VAR_SHIFT 16
|
||||
#define GICD_IIDR_VAR_MASK 0x000f0000
|
||||
#define GICD_IIDR_VAR(x) \
|
||||
(((x) & GICD_IIDR_VAR_MASK) >> GICD_IIDR_VAR_SHIFT)
|
||||
#define GICD_IIDR_REV_SHIFT 12
|
||||
#define GICD_IIDR_REV_MASK 0x0000f000
|
||||
#define GICD_IIDR_REV(x) \
|
||||
(((x) & GICD_IIDR_REV_MASK) >> GICD_IIDR_REV_SHIFT)
|
||||
#define GICD_IIDR_IMPL_SHIFT 0
|
||||
#define GICD_IIDR_IMPL_MASK 0x00000fff
|
||||
#define GICD_IIDR_IMPL(x) \
|
||||
(((x) & GICD_IIDR_IMPL_MASK) >> GICD_IIDR_IMPL_SHIFT)
|
||||
#define GICD_IGROUPR(n) (0x0080 + (((n) >> 5) * 4)) /* v1 ICDISER */
|
||||
#define GICD_ISENABLER(n) (0x0100 + (((n) >> 5) * 4)) /* v1 ICDISER */
|
||||
#define GICD_ICENABLER(n) (0x0180 + (((n) >> 5) * 4)) /* v1 ICDICER */
|
||||
#define GICD_ISPENDR(n) (0x0200 + (((n) >> 5) * 4)) /* v1 ICDISPR */
|
||||
#define GICD_ICPENDR(n) (0x0280 + (((n) >> 5) * 4)) /* v1 ICDICPR */
|
||||
#define GICD_ICACTIVER(n) (0x0380 + (((n) >> 5) * 4)) /* v1 ICDABR */
|
||||
#define GICD_IPRIORITYR(n) (0x0400 + (((n) >> 2) * 4)) /* v1 ICDIPR */
|
||||
#define GICD_ITARGETSR(n) (0x0800 + (((n) >> 2) * 4)) /* v1 ICDIPTR */
|
||||
#define GICD_ICFGR(n) (0x0C00 + (((n) >> 4) * 4)) /* v1 ICDICFR */
|
||||
/* First bit is a polarity bit (0 - low, 1 - high) */
|
||||
#define GICD_ICFGR_POL_LOW (0 << 0)
|
||||
#define GICD_ICFGR_POL_HIGH (1 << 0)
|
||||
#define GICD_ICFGR_POL_MASK 0x1
|
||||
/* Second bit is a trigger bit (0 - level, 1 - edge) */
|
||||
#define GICD_ICFGR_TRIG_LVL (0 << 1)
|
||||
#define GICD_ICFGR_TRIG_EDGE (1 << 1)
|
||||
#define GICD_ICFGR_TRIG_MASK 0x2
|
||||
#define GICD_SGIR 0x0F00 /* v1 ICDSGIR */
|
||||
#define GICD_SGI_TARGET_SHIFT 16
|
||||
|
||||
#endif /* _GIC_COMMON_H_ */
|
||||
Loading…
Reference in a new issue