Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

interrupt_controller: gic: Support multiple GIC versions #21508

Merged
merged 2 commits into from
Dec 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion drivers/interrupt_controller/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: Apache-2.0

zephyr_sources_ifdef(CONFIG_ARCV2_INTERRUPT_UNIT intc_arcv2_irq_unit.c)
zephyr_sources_ifdef(CONFIG_GIC intc_gic_400.c)
zephyr_sources_ifdef(CONFIG_GIC intc_gic.c)
zephyr_sources_ifdef(CONFIG_IOAPIC intc_ioapic.c)
zephyr_sources_ifdef(CONFIG_LOAPIC intc_loapic.c intc_system_apic.c)
zephyr_sources_ifdef(CONFIG_LOAPIC_SPURIOUS_VECTOR intc_loapic_spurious.S)
Expand Down
9 changes: 2 additions & 7 deletions drivers/interrupt_controller/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,6 @@ config VEXRISCV_LITEX_IRQ
help
IRQ implementation for LiteX VexRiscv

config GIC
bool "ARM Generic Interrupt Controller (GIC)"
depends on CPU_CORTEX_R
help
The ARM Generic Interrupt Controller works with Cortex-A and
Cortex-R processors.

source "drivers/interrupt_controller/Kconfig.multilevel"

source "drivers/interrupt_controller/Kconfig.loapic"
Expand All @@ -60,4 +53,6 @@ source "drivers/interrupt_controller/Kconfig.rv32m1"

source "drivers/interrupt_controller/Kconfig.sam0"

source "drivers/interrupt_controller/Kconfig.gic"

endmenu
39 changes: 39 additions & 0 deletions drivers/interrupt_controller/Kconfig.gic
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# ARM Generic Interrupt Controller (GIC) configuration

# Copyright (c) 2019 Stephanos Ioannidis <root@stephanos.io>
# SPDX-License-Identifier: Apache-2.0

if CPU_CORTEX

config GIC
bool

config GIC_V1
stephanosio marked this conversation as resolved.
Show resolved Hide resolved
bool
select GIC
help
The ARM Generic Interrupt Controller v1 (e.g. PL390) works with the
ARM Cortex-family processors.

config GIC_V2
bool
select GIC
help
The ARM Generic Interrupt Controller v2 (e.g. GIC-400) works with the
ARM Cortex-family processors.

config GIC_V3
bool
select GIC
help
The ARM Generic Interrupt Controller v3 (e.g. GIC-500 and GIC-600)
works with the ARM Cortex-family processors.

config GIC_VER
int
depends on GIC
default 1 if GIC_V1
default 2 if GIC_V2
default 3 if GIC_V3

endif # CPU_CORTEX
Original file line number Diff line number Diff line change
@@ -1,48 +1,25 @@
/*
* Copyright (c) 2018 Marvell
* Copyright (c) 2018 Lexmark International, Inc.
* Copyright (c) 2019 Stephanos Ioannidis <root@stephanos.io>
*
* SPDX-License-Identifier: Apache-2.0
*/

/*
* NOTE: This driver currently implements the GICv1 and GICv2 interfaces. The
* GICv3 interface is not supported.
*/

#include <device.h>
#include <sw_isr_table.h>
#include <irq_nextlevel.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <drivers/interrupt_controller/gic.h>

#define DT_GIC_DIST_BASE DT_INST_0_ARM_GIC_BASE_ADDRESS_0
#define DT_GIC_CPU_BASE DT_INST_0_ARM_GIC_BASE_ADDRESS_1

#define GICD_CTRL (DT_GIC_DIST_BASE + 0)
#define GICD_TYPER (DT_GIC_DIST_BASE + 0x4)
#define GICD_IIDR (DT_GIC_DIST_BASE + 0x8)
#define GICD_IGROUPRn (DT_GIC_DIST_BASE + 0x80)
#define GICD_ISENABLERn (DT_GIC_DIST_BASE + 0x100)
#define GICD_ICENABLERn (DT_GIC_DIST_BASE + 0x180)
#define GICD_ISPENDRn (DT_GIC_DIST_BASE + 0x200)
#define GICD_ICPENDRn (DT_GIC_DIST_BASE + 0x280)
#define GICD_ISACTIVERn (DT_GIC_DIST_BASE + 0x300)
#define GICD_ICACTIVERn (DT_GIC_DIST_BASE + 0x380)
#define GICD_IPRIORITYRn (DT_GIC_DIST_BASE + 0x400)
#define GICD_ITARGETSRn (DT_GIC_DIST_BASE + 0x800)
#define GICD_ICFGRn (DT_GIC_DIST_BASE + 0xc00)
#define GICD_SGIR (DT_GIC_DIST_BASE + 0xf00)

#define GICC_CTRL (DT_GIC_CPU_BASE + 0x00)
#define GICC_PMR (DT_GIC_CPU_BASE + 0x04)
#define GICC_BPR (DT_GIC_CPU_BASE + 0x08)
#define GICC_IAR (DT_GIC_CPU_BASE + 0x0c)
#define GICC_EOIR (DT_GIC_CPU_BASE + 0x10)

#define GICC_ENABLE 3
#define GICC_DIS_BYPASS_MASK 0x1e0

#define NO_GIC_INT_PENDING 1023

#define GIC_SPI_INT_BASE 32

#define GIC_INT_TYPE_MASK 0x3
#define GIC_INT_TYPE_EDGE (1 << 1)
#if CONFIG_GIC_VER >= 3
#error "GICv3 and above are not supported"
#endif

struct gic_ictl_config {
u32_t isr_table_offset;
Expand All @@ -61,7 +38,7 @@ static void gic_dist_init(void)
* Disable the forwarding of pending interrupts
* from the Distributor to the CPU interfaces
*/
sys_write32(0, GICD_CTRL);
sys_write32(0, GICD_CTLR);

/*
* Set all global interrupts to this CPU only.
Expand All @@ -88,15 +65,17 @@ static void gic_dist_init(void)
* as these enables are banked registers.
*/
for (i = GIC_SPI_INT_BASE; i < gic_irqs; i += 32) {
#ifndef CONFIG_GIC_V1
sys_write32(0xffffffff, GICD_ICACTIVERn + i / 8);
#endif
sys_write32(0xffffffff, GICD_ICENABLERn + i / 8);
}

/*
* Enable the forwarding of pending interrupts
* from the Distributor to the CPU interfaces
*/
sys_write32(1, GICD_CTRL);
sys_write32(1, GICD_CTLR);
}

static void gic_cpu_init(void)
Expand All @@ -108,7 +87,9 @@ static void gic_cpu_init(void)
* Deal with the banked PPI and SGI interrupts - disable all
* PPI interrupts, ensure all SGI interrupts are enabled.
*/
#ifndef CONFIG_GIC_V1
sys_write32(0xffffffff, GICD_ICACTIVERn);
#endif
sys_write32(0xffff0000, GICD_ICENABLERn);
sys_write32(0x0000ffff, GICD_ISENABLERn);

Expand All @@ -123,10 +104,12 @@ static void gic_cpu_init(void)
/*
* Enable interrupts and signal them using the IRQ signal.
*/
val = sys_read32(GICC_CTRL);
val &= GICC_DIS_BYPASS_MASK;
val |= GICC_ENABLE;
sys_write32(val, GICC_CTRL);
val = sys_read32(GICC_CTLR);
#ifndef CONFIG_GIC_V1
val &= ~GICC_CTLR_BYPASS_MASK;
#endif
val |= GICC_CTLR_ENABLE_MASK;
sys_write32(val, GICC_CTLR);
}

static void gic_irq_enable(struct device *dev, unsigned int irq)
Expand Down Expand Up @@ -168,9 +151,9 @@ static void gic_irq_set_priority(struct device *dev,
int_off = (irq % 16) * 2;

val = sys_read8(GICD_ICFGRn + int_grp);
val &= ~(GIC_INT_TYPE_MASK << int_off);
val &= ~(GICC_ICFGR_MASK << int_off);
if (flags & IRQ_TYPE_EDGE)
val |= (GIC_INT_TYPE_EDGE << int_off);
val |= (GICC_ICFGR_TYPE << int_off);
sys_write8(val, GICD_ICFGRn + int_grp);
}

Expand All @@ -184,7 +167,7 @@ static void gic_isr(void *arg)
irq = sys_read32(GICC_IAR);
irq &= 0x3ff;

if (irq == NO_GIC_INT_PENDING) {
if (irq == GICC_IAR_SPURIOUS) {
printk("gic: Invalid interrupt\n");
return;
}
Expand Down
Loading