zephyr/include/drivers/interrupt_controller/gic.h
Sandeep Tripathy bd985dcd67 drivers: add GIC V3 driver
Add basic driver for GIC V3 interrupt controller.

This implementation supports
 - distributor, re-distributor and cpu interface initialization
 - configuration and handling of SPI, PPI and SGI.
 - V2 Legacy mode is not supported and uses system interface.

Current implementation supports GIC secure state only.
All interrupts are routed to Secure EL1 as 'irq' by configuring
them as Group1 Secure.

TODO:
- MPIDR based affinity routing setting.
- percpu redistributor probe
- message based SPI and SGI generation api
- EL1NS support. Legacy mode support.
- LPI/ITS is not supported.

Signed-off-by: Sandeep Tripathy <sandeep.tripathy@broadcom.com>
2020-05-07 14:22:53 +02:00

317 lines
6.4 KiB
C

/*
* Copyright (c) 2019 Stephanos Ioannidis <root@stephanos.io>
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Driver for ARM Generic Interrupt Controller
*
* The Generic Interrupt Controller (GIC) is the default interrupt controller
* for the ARM A and R profile cores. This driver is used by the ARM arch
* implementation to handle interrupts.
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_GIC_H_
#define ZEPHYR_INCLUDE_DRIVERS_GIC_H_
#include <zephyr/types.h>
#include <device.h>
/*
* GIC Register Interface Base Addresses
*/
#define GIC_DIST_BASE DT_REG_ADDR_BY_IDX(DT_INST(0, arm_gic), 0)
#define GIC_CPU_BASE DT_REG_ADDR_BY_IDX(DT_INST(0, arm_gic), 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
*/
/* 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 */
/* GICD_SGIR */
#define GICD_SGIR_TGTFILT(x) (x << 24)
#define GICD_SGIR_TGTFILT_CPULIST GICD_SGIR_TGTFILT(0b00)
#define GICD_SGIR_TGTFILT_ALLBUTREQ GICD_SGIR_TGTFILT(0b01)
#define GICD_SGIR_TGTFILT_REQONLY GICD_SGIR_TGTFILT(0b10)
#define GICD_SGIR_CPULIST(x) (x << 16)
#define GICD_SGIR_CPULIST_CPU(n) GICD_SGIR_CPULIST(BIT(n))
#define GICD_SGIR_NSATT BIT(15)
#define GICD_SGIR_SGIINTID(x) (x)
#endif /* CONFIG_GIC_VER <= 2 */
/* GICD_ICFGR */
#define GICD_ICFGR_MASK BIT_MASK(2)
#define GICD_ICFGR_TYPE BIT(1)
/* GICD_TYPER.ITLinesNumber 0:4 */
#define GICD_TYPER_ITLINESNUM_MASK 0x1f
/*
* Common Helper Constants
*/
#define GIC_SPI_INT_BASE 32
#define GIC_NUM_INTR_PER_REG 32
#define GIC_NUM_CFG_PER_REG 16
#define GIC_NUM_PRI_PER_REG 4
/* GIC idle priority : value '0xff' will allow all interrupts */
#define GIC_IDLE_PRIO 0xff
/* Priority levels 0:255 */
#define GIC_PRI_MASK 0xff
/*
* '0xa0'is used to initialize each interrtupt default priority.
* This is an arbitrary value in current context.
* Any value '0x80' to '0xff' will work for both NS and S state.
* The values of individual interrupt and default has to be chosen
* carefully if PMR and BPR based nesting and preemption has to be done.
*/
#define GIC_INT_DEF_PRI_X4 0xa0a0a0a0
/* GIC special interrupt id */
#define GIC_INTID_SPURIOUS 1023
/* Fixme: update from platform specific define or dt */
#define GIC_NUM_CPU_IF 1
/* Fixme: arch support need to provide api/macro in SMP implementation */
#define GET_CPUID 0
#ifndef _ASMLANGUAGE
/*
* GIC Driver Interface Functions
*/
/**
* @brief Initialise ARM GIC driver
*
* @return 0 if successful
*/
int arm_gic_init(void);
/**
* @brief Enable interrupt
*
* @param irq interrupt ID
*/
void arm_gic_irq_enable(unsigned int irq);
/**
* @brief Disable interrupt
*
* @param irq interrupt ID
*/
void arm_gic_irq_disable(unsigned int irq);
/**
* @brief Check if an interrupt is enabled
*
* @param irq interrupt ID
* @return Returns true if interrupt is enabled, false otherwise
*/
bool arm_gic_irq_is_enabled(unsigned int irq);
/**
* @brief Set interrupt priority
*
* @param irq interrupt ID
* @param prio interrupt priority
* @param flags interrupt flags
*/
void arm_gic_irq_set_priority(
unsigned int irq, unsigned int prio, unsigned int flags);
/**
* @brief Get active interrupt ID
*
* @return Returns the ID of an active interrupt
*/
unsigned int arm_gic_get_active(void);
/**
* @brief Signal end-of-interrupt
*
* @param irq interrupt ID
*/
void arm_gic_eoi(unsigned int irq);
#endif /* !_ASMLANGUAGE */
#endif /* ZEPHYR_INCLUDE_DRIVERS_GIC_H_ */