diff --git a/drivers/interrupt_controller/CMakeLists.txt b/drivers/interrupt_controller/CMakeLists.txt index eb6131c3197..54ba3de19b0 100644 --- a/drivers/interrupt_controller/CMakeLists.txt +++ b/drivers/interrupt_controller/CMakeLists.txt @@ -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) diff --git a/drivers/interrupt_controller/intc_gic_400.c b/drivers/interrupt_controller/intc_gic.c similarity index 74% rename from drivers/interrupt_controller/intc_gic_400.c rename to drivers/interrupt_controller/intc_gic.c index 5351b40f774..9aff07d006c 100644 --- a/drivers/interrupt_controller/intc_gic_400.c +++ b/drivers/interrupt_controller/intc_gic.c @@ -1,48 +1,25 @@ /* * Copyright (c) 2018 Marvell * Copyright (c) 2018 Lexmark International, Inc. + * Copyright (c) 2019 Stephanos Ioannidis * * SPDX-License-Identifier: Apache-2.0 */ +/* + * NOTE: This driver currently implements the GICv1 and GICv2 interfaces. The + * GICv3 interface is not supported. + */ + #include #include #include #include +#include -#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; @@ -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. @@ -88,7 +65,9 @@ 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); } @@ -96,7 +75,7 @@ static void gic_dist_init(void) * 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) @@ -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); @@ -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) @@ -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); } @@ -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; } diff --git a/include/drivers/interrupt_controller/gic.h b/include/drivers/interrupt_controller/gic.h new file mode 100644 index 00000000000..8cedd88a952 --- /dev/null +++ b/include/drivers/interrupt_controller/gic.h @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2019 Stephanos Ioannidis + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_GIC_H_ +#define ZEPHYR_INCLUDE_DRIVERS_GIC_H_ + +#include + +/* + * GIC Register Interface Base Addresses + */ + +#define GIC_DIST_BASE DT_INST_0_ARM_GIC_BASE_ADDRESS_0 +#define GIC_CPU_BASE DT_INST_0_ARM_GIC_BASE_ADDRESS_1 + +/* + * GIC Distributor Interface + */ + +/* + * 0x000 Distributor Control Register + * v1 ICDDCR + * v2/v3 GICD_CTLR + */ +#define GICD_CTLR (GIC_DIST_BASE + 0x0) + +/* + * 0x004 Interrupt Controller Type Register + * v1 ICDICTR + * v2/v3 GICD_TYPER + */ +#define GICD_TYPER (GIC_DIST_BASE + 0x4) + +/* + * 0x008 Distributor Implementer Identification Register + * v1 ICDIIDR + * v2/v3 GICD_IIDR + */ +#define GICD_IIDR (GIC_DIST_BASE + 0x8) + +/* + * 0x080 Interrupt Group Registers + * v1 ICDISRn + * v2/v3 GICD_IGROUPRn + */ +#define GICD_IGROUPRn (GIC_DIST_BASE + 0x80) + +/* + * 0x100 Interrupt Set-Enable Reigsters + * v1 ICDISERn + * v2/v3 GICD_ISENABLERn + */ +#define GICD_ISENABLERn (GIC_DIST_BASE + 0x100) + +/* + * 0x180 Interrupt Clear-Enable Registers + * v1 ICDICERn + * v2/v3 GICD_ICENABLERn + */ +#define GICD_ICENABLERn (GIC_DIST_BASE + 0x180) + +/* + * 0x200 Interrupt Set-Pending Registers + * v1 ICDISPRn + * v2/v3 GICD_ISPENDRn + */ +#define GICD_ISPENDRn (GIC_DIST_BASE + 0x200) + +/* + * 0x280 Interrupt Clear-Pending Registers + * v1 ICDICPRn + * v2/v3 GICD_ICPENDRn + */ +#define GICD_ICPENDRn (GIC_DIST_BASE + 0x280) + +/* + * 0x300 Interrupt Set-Active Registers + * v1 ICDABRn + * v2/v3 GICD_ISACTIVERn + */ +#define GICD_ISACTIVERn (GIC_DIST_BASE + 0x300) + +#if CONFIG_GIC_VER >= 2 +/* + * 0x380 Interrupt Clear-Active Registers + * v2/v3 GICD_ICACTIVERn + */ +#define GICD_ICACTIVERn (GIC_DIST_BASE + 0x380) +#endif + +/* + * 0x400 Interrupt Priority Registers + * v1 ICDIPRn + * v2/v3 GICD_IPRIORITYRn + */ +#define GICD_IPRIORITYRn (GIC_DIST_BASE + 0x400) + +/* + * 0x800 Interrupt Processor Targets Registers + * v1 ICDIPTRn + * v2/v3 GICD_ITARGETSRn + */ +#define GICD_ITARGETSRn (GIC_DIST_BASE + 0x800) + +/* + * 0xC00 Interrupt Configuration Registers + * v1 ICDICRn + * v2/v3 GICD_ICFGRn + */ +#define GICD_ICFGRn (GIC_DIST_BASE + 0xc00) + +/* + * 0xF00 Software Generated Interrupt Register + * v1 ICDSGIR + * v2/v3 GICD_SGIR + */ +#define GICD_SGIR (GIC_DIST_BASE + 0xf00) + +/* + * GIC CPU Interface + */ + +#if CONFIG_GIC_VER <= 2 + +/* + * 0x0000 CPU Interface Control Register + * v1 ICCICR + * v2/v3 GICC_CTLR + */ +#define GICC_CTLR (GIC_CPU_BASE + 0x0) + +/* + * 0x0004 Interrupt Priority Mask Register + * v1 ICCPMR + * v2/v3 GICC_PMR + */ +#define GICC_PMR (GIC_CPU_BASE + 0x4) + +/* + * 0x0008 Binary Point Register + * v1 ICCBPR + * v2/v3 GICC_BPR + */ +#define GICC_BPR (GIC_CPU_BASE + 0x8) + +/* + * 0x000C Interrupt Acknowledge Register + * v1 ICCIAR + * v2/v3 GICC_IAR + */ +#define GICC_IAR (GIC_CPU_BASE + 0xc) + +/* + * 0x0010 End of Interrupt Register + * v1 ICCEOIR + * v2/v3 GICC_EOIR + */ +#define GICC_EOIR (GIC_CPU_BASE + 0x10) + + +/* + * Helper Constants + */ + +#define GIC_SPI_INT_BASE 32 + +/* GICC_CTLR */ +#define GICC_CTLR_ENABLEGRP0 BIT(0) +#define GICC_CTLR_ENABLEGRP1 BIT(1) + +#define GICC_CTLR_ENABLE_MASK (GICC_CTLR_ENABLEGRP0 | GICC_CTLR_ENABLEGRP1) + +#if defined(CONFIG_GIC_V2) + +#define GICC_CTLR_FIQBYPDISGRP0 BIT(5) +#define GICC_CTLR_IRQBYPDISGRP0 BIT(6) +#define GICC_CTLR_FIQBYPDISGRP1 BIT(7) +#define GICC_CTLR_IRQBYPDISGRP1 BIT(8) + +#define GICC_CTLR_BYPASS_MASK (GICC_CTLR_FIQBYPDISGRP0 | \ + GICC_CTLR_IRQBYPDISGRP1 | \ + GICC_CTLR_FIQBYPDISGRP1 | \ + GICC_CTLR_IRQBYPDISGRP1) + +#endif /* CONFIG_GIC_V2 */ + +/* GICC_IAR */ +#define GICC_IAR_SPURIOUS 1023 + +/* GICC_ICFGR */ +#define GICC_ICFGR_MASK BIT_MASK(2) +#define GICC_ICFGR_TYPE BIT(1) + +#endif /* CONFIG_GIC_VER <= 2 */ + +#endif /* ZEPHYR_INCLUDE_DRIVERS_GIC_H_ */