diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/aarch64/cpu/cpu_helpers.S | 66 | ||||
-rw-r--r-- | arch/system/gic/aarch64/gic_v3_sysregs.S | 89 | ||||
-rw-r--r-- | arch/system/gic/gic.h | 217 | ||||
-rw-r--r-- | arch/system/gic/gic_v2.c | 426 | ||||
-rw-r--r-- | arch/system/gic/gic_v3.c | 46 |
5 files changed, 844 insertions, 0 deletions
diff --git a/arch/aarch64/cpu/cpu_helpers.S b/arch/aarch64/cpu/cpu_helpers.S new file mode 100644 index 0000000..600b72f --- /dev/null +++ b/arch/aarch64/cpu/cpu_helpers.S @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013, ARM Limited. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 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. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +#include <arch.h> + + .weak cpu_reset_handler + + + .section aarch64_code, "ax"; .align 3 + +cpu_reset_handler:; .type cpu_reset_handler, %function + mov x19, x30 // lr + + /* --------------------------------------------- + * As a bare minimal enable the SMP bit and the + * I$ for all aarch64 processors. Also set the + * exception vector to something sane. + * --------------------------------------------- + */ + adr x0, early_exceptions + bl write_vbar + + bl read_midr + lsr x0, x0, #MIDR_PN_SHIFT + and x0, x0, #MIDR_PN_MASK + cmp x0, #MIDR_PN_A57 + b.eq smp_setup_begin + cmp x0, #MIDR_PN_A53 + b.ne smp_setup_end +smp_setup_begin: + bl read_cpuectlr + orr x0, x0, #CPUECTLR_SMP_BIT + bl write_cpuectlr +smp_setup_end: + bl read_sctlr + orr x0, x0, #SCTLR_I_BIT + bl write_sctlr + + ret x19 diff --git a/arch/system/gic/aarch64/gic_v3_sysregs.S b/arch/system/gic/aarch64/gic_v3_sysregs.S new file mode 100644 index 0000000..3a2fb6e --- /dev/null +++ b/arch/system/gic/aarch64/gic_v3_sysregs.S @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013, ARM Limited. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 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. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + + .globl read_icc_sre_el1 + .globl read_icc_sre_el2 + .globl read_icc_sre_el3 + .globl write_icc_sre_el1 + .globl write_icc_sre_el2 + .globl write_icc_sre_el3 + .globl write_icc_pmr_el1 + + +/* + * Register definitions used by GCC for GICv3 access. + * These are defined by ARMCC, so keep them in the GCC specific code for now. + */ +#define ICC_SRE_EL1 S3_0_C12_C12_5 +#define ICC_SRE_EL2 S3_4_C12_C9_5 +#define ICC_SRE_EL3 S3_6_C12_C12_5 +#define ICC_CTLR_EL1 S3_0_C12_C12_4 +#define ICC_CTLR_EL3 S3_6_C12_C12_4 +#define ICC_PMR_EL1 S3_0_C4_C6_0 + + .section platform_code, "ax"; .align 3 + +read_icc_sre_el1:; .type read_icc_sre_el1, %function + mrs x0, ICC_SRE_EL1 + ret + + +read_icc_sre_el2:; .type read_icc_sre_el2, %function + mrs x0, ICC_SRE_EL2 + ret + + +read_icc_sre_el3:; .type read_icc_sre_el3, %function + mrs x0, ICC_SRE_EL3 + ret + + +write_icc_sre_el1:; .type write_icc_sre_el1, %function + msr ICC_SRE_EL1, x0 + isb + ret + + +write_icc_sre_el2:; .type write_icc_sre_el2, %function + msr ICC_SRE_EL2, x0 + isb + ret + + +write_icc_sre_el3:; .type write_icc_sre_el3, %function + msr ICC_SRE_EL3, x0 + isb + ret + + +write_icc_pmr_el1:; .type write_icc_pmr_el1, %function + msr ICC_PMR_EL1, x0 + isb + ret diff --git a/arch/system/gic/gic.h b/arch/system/gic/gic.h new file mode 100644 index 0000000..91ada03 --- /dev/null +++ b/arch/system/gic/gic.h @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2013, ARM Limited. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 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. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +#ifndef __GIC_H__ +#define __GIC_H__ + +#define MAX_SPIS 480 +#define MAX_PPIS 14 +#define MAX_SGIS 16 + +#define GRP0 0 +#define GRP1 1 +#define MAX_PRI_VAL 0xff + +#define ENABLE_GRP0 (1 << 0) +#define ENABLE_GRP1 (1 << 1) + +/* Distributor interface definitions */ +#define GICD_CTLR 0x0 +#define GICD_TYPER 0x4 +#define GICD_IGROUPR 0x80 +#define GICD_ISENABLER 0x100 +#define GICD_ICENABLER 0x180 +#define GICD_ISPENDR 0x200 +#define GICD_ICPENDR 0x280 +#define GICD_ISACTIVER 0x300 +#define GICD_ICACTIVER 0x380 +#define GICD_IPRIORITYR 0x400 +#define GICD_ITARGETSR 0x800 +#define GICD_ICFGR 0xC00 +#define GICD_SGIR 0xF00 +#define GICD_CPENDSGIR 0xF10 +#define GICD_SPENDSGIR 0xF20 + +#define IGROUPR_SHIFT 5 +#define ISENABLER_SHIFT 5 +#define ICENABLER_SHIFT ISENABLER_SHIFT +#define ISPENDR_SHIFT 5 +#define ICPENDR_SHIFT ISPENDR_SHIFT +#define ISACTIVER_SHIFT 5 +#define ICACTIVER_SHIFT ISACTIVER_SHIFT +#define IPRIORITYR_SHIFT 2 +#define ITARGETSR_SHIFT 2 +#define ICFGR_SHIFT 4 +#define CPENDSGIR_SHIFT 2 +#define SPENDSGIR_SHIFT CPENDSGIR_SHIFT + +/* GICD_TYPER bit definitions */ +#define IT_LINES_NO_MASK 0x1f + +/* Physical CPU Interface registers */ +#define GICC_CTLR 0x0 +#define GICC_PMR 0x4 +#define GICC_BPR 0x8 +#define GICC_IAR 0xC +#define GICC_EOIR 0x10 +#define GICC_RPR 0x14 +#define GICC_HPPIR 0x18 +#define GICC_IIDR 0xFC +#define GICC_DIR 0x1000 +#define GICC_PRIODROP GICC_EOIR + +/* GICC_CTLR bit definitions */ +#define EOI_MODE_NS (1 << 10) +#define EOI_MODE_S (1 << 9) +#define IRQ_BYP_DIS_GRP1 (1 << 8) +#define FIQ_BYP_DIS_GRP1 (1 << 7) +#define IRQ_BYP_DIS_GRP0 (1 << 6) +#define FIQ_BYP_DIS_GRP0 (1 << 5) +#define CBPR (1 << 4) +#define FIQ_EN (1 << 3) +#define ACK_CTL (1 << 2) + +/* GICC_IIDR bit masks and shifts */ +#define GICC_IIDR_PID_SHIFT 20 +#define GICC_IIDR_ARCH_SHIFT 16 +#define GICC_IIDR_REV_SHIFT 12 +#define GICC_IIDR_IMP_SHIFT 0 + +#define GICC_IIDR_PID_MASK 0xfff +#define GICC_IIDR_ARCH_MASK 0xf +#define GICC_IIDR_REV_MASK 0xf +#define GICC_IIDR_IMP_MASK 0xfff + +/* HYP view virtual CPU Interface registers */ +#define GICH_CTL 0x0 +#define GICH_VTR 0x4 +#define GICH_ELRSR0 0x30 +#define GICH_ELRSR1 0x34 +#define GICH_APR0 0xF0 +#define GICH_LR_BASE 0x100 + +/* Virtual CPU Interface registers */ +#define GICV_CTL 0x0 +#define GICV_PRIMASK 0x4 +#define GICV_BP 0x8 +#define GICV_INTACK 0xC +#define GICV_EOI 0x10 +#define GICV_RUNNINGPRI 0x14 +#define GICV_HIGHESTPEND 0x18 +#define GICV_DEACTIVATE 0x1000 + +/* GICv3 Re-distributor interface registers & shifts */ +#define GICR_PCPUBASE_SHIFT 0x11 +#define GICR_WAKER 0x14 + +/* GICR_WAKER bit definitions */ +#define WAKER_CA (1UL << 2) +#define WAKER_PS (1UL << 1) + +/* GICv3 ICC_SRE register bit definitions*/ +#define ICC_SRE_EN (1UL << 3) +#define ICC_SRE_SRE (1UL << 0) + +#ifndef __ASSEMBLY__ + +/******************************************************************************* + * Function prototypes + ******************************************************************************/ +extern inline unsigned int gicd_read_typer(unsigned int); +extern inline unsigned int gicd_read_ctlr(unsigned int); +extern unsigned int gicd_read_igroupr(unsigned int, unsigned int); +extern unsigned int gicd_read_isenabler(unsigned int, unsigned int); +extern unsigned int gicd_read_icenabler(unsigned int, unsigned int); +extern unsigned int gicd_read_ispendr(unsigned int, unsigned int); +extern unsigned int gicd_read_icpendr(unsigned int, unsigned int); +extern unsigned int gicd_read_isactiver(unsigned int, unsigned int); +extern unsigned int gicd_read_icactiver(unsigned int, unsigned int); +extern unsigned int gicd_read_ipriorityr(unsigned int, unsigned int); +extern unsigned int gicd_read_itargetsr(unsigned int, unsigned int); +extern unsigned int gicd_read_icfgr(unsigned int, unsigned int); +extern unsigned int gicd_read_sgir(unsigned int); +extern unsigned int gicd_read_cpendsgir(unsigned int, unsigned int); +extern unsigned int gicd_read_spendsgir(unsigned int, unsigned int); +extern inline void gicd_write_ctlr(unsigned int, unsigned int); +extern void gicd_write_igroupr(unsigned int, unsigned int, unsigned int); +extern void gicd_write_isenabler(unsigned int, unsigned int, unsigned int); +extern void gicd_write_icenabler(unsigned int, unsigned int, unsigned int); +extern void gicd_write_ispendr(unsigned int, unsigned int, unsigned int); +extern void gicd_write_icpendr(unsigned int, unsigned int, unsigned int); +extern void gicd_write_isactiver(unsigned int, unsigned int, unsigned int); +extern void gicd_write_icactiver(unsigned int, unsigned int, unsigned int); +extern void gicd_write_ipriorityr(unsigned int, unsigned int, unsigned int); +extern void gicd_write_itargetsr(unsigned int, unsigned int, unsigned int); +extern void gicd_write_icfgr(unsigned int, unsigned int, unsigned int); +extern void gicd_write_sgir(unsigned int, unsigned int); +extern void gicd_write_cpendsgir(unsigned int, unsigned int, unsigned int); +extern void gicd_write_spendsgir(unsigned int, unsigned int, unsigned int); +extern unsigned int gicd_get_igroupr(unsigned int, unsigned int); +extern void gicd_set_igroupr(unsigned int, unsigned int); +extern void gicd_clr_igroupr(unsigned int, unsigned int); +extern void gicd_set_isenabler(unsigned int, unsigned int); +extern void gicd_set_icenabler(unsigned int, unsigned int); +extern void gicd_set_ispendr(unsigned int, unsigned int); +extern void gicd_set_icpendr(unsigned int, unsigned int); +extern void gicd_set_isactiver(unsigned int, unsigned int); +extern void gicd_set_icactiver(unsigned int, unsigned int); +extern void gicd_set_ipriorityr(unsigned int, unsigned int, unsigned int); +extern void gicd_set_itargetsr(unsigned int, unsigned int, unsigned int); +extern inline unsigned int gicc_read_ctlr(unsigned int); +extern inline unsigned int gicc_read_pmr(unsigned int); +extern inline unsigned int gicc_read_BPR(unsigned int); +extern inline unsigned int gicc_read_IAR(unsigned int); +extern inline unsigned int gicc_read_EOIR(unsigned int); +extern inline unsigned int gicc_read_hppir(unsigned int); +extern inline unsigned int gicc_read_iidr(unsigned int); +extern inline unsigned int gicc_read_dir(unsigned int); +extern inline void gicc_write_ctlr(unsigned int, unsigned int); +extern inline void gicc_write_pmr(unsigned int, unsigned int); +extern inline void gicc_write_BPR(unsigned int, unsigned int); +extern inline void gicc_write_IAR(unsigned int, unsigned int); +extern inline void gicc_write_EOIR(unsigned int, unsigned int); +extern inline void gicc_write_hppir(unsigned int, unsigned int); +extern inline void gicc_write_dir(unsigned int, unsigned int); + +/* GICv3 functions */ +extern inline unsigned int gicr_read_waker(unsigned int); +extern inline void gicr_write_waker(unsigned int, unsigned int); +extern unsigned int read_icc_sre_el1(void); +extern unsigned int read_icc_sre_el2(void); +extern unsigned int read_icc_sre_el3(void); +extern void write_icc_sre_el1(unsigned int); +extern void write_icc_sre_el2(unsigned int); +extern void write_icc_sre_el3(unsigned int); +extern void write_icc_pmr_el1(unsigned int); + +#endif /*__ASSEMBLY__*/ + +#endif /* __GIC_H__ */ + diff --git a/arch/system/gic/gic_v2.c b/arch/system/gic/gic_v2.c new file mode 100644 index 0000000..4b3d0c5 --- /dev/null +++ b/arch/system/gic/gic_v2.c @@ -0,0 +1,426 @@ +/* + * Copyright (c) 2013, ARM Limited. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 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. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +#include <gic.h> +#include <mmio.h> + +/******************************************************************************* + * GIC Distributor interface accessesors for reading entire registers + ******************************************************************************/ +inline unsigned int gicd_read_ctlr(unsigned int base) +{ + return mmio_read_32(base + GICD_CTLR); +} + +inline unsigned int gicd_read_typer(unsigned int base) +{ + return mmio_read_32(base + GICD_TYPER); +} + +unsigned int gicd_read_igroupr(unsigned int base, unsigned int id) +{ + unsigned n = id >> IGROUPR_SHIFT; + return mmio_read_32(base + GICD_IGROUPR + (n << 2)); +} + +unsigned int gicd_read_isenabler(unsigned int base, unsigned int id) +{ + unsigned n = id >> ISENABLER_SHIFT; + return mmio_read_32(base + GICD_ISENABLER + (n << 2)); +} + +unsigned int gicd_read_icenabler(unsigned int base, unsigned int id) +{ + unsigned n = id >> ICENABLER_SHIFT; + return mmio_read_32(base + GICD_ICENABLER + (n << 2)); +} + +unsigned int gicd_read_ispendr(unsigned int base, unsigned int id) +{ + unsigned n = id >> ISPENDR_SHIFT; + return mmio_read_32(base + GICD_ISPENDR + (n << 2)); +} + +unsigned int gicd_read_icpendr(unsigned int base, unsigned int id) +{ + unsigned n = id >> ICPENDR_SHIFT; + return mmio_read_32(base + GICD_ICPENDR + (n << 2)); +} + +unsigned int gicd_read_isactiver(unsigned int base, unsigned int id) +{ + unsigned n = id >> ISACTIVER_SHIFT; + return mmio_read_32(base + GICD_ISACTIVER + (n << 2)); +} + +unsigned int gicd_read_icactiver(unsigned int base, unsigned int id) +{ + unsigned n = id >> ICACTIVER_SHIFT; + return mmio_read_32(base + GICD_ICACTIVER + (n << 2)); +} + +unsigned int gicd_read_ipriorityr(unsigned int base, unsigned int id) +{ + unsigned n = id >> IPRIORITYR_SHIFT; + return mmio_read_32(base + GICD_IPRIORITYR + (n << 2)); +} + +unsigned int gicd_read_itargetsr(unsigned int base, unsigned int id) +{ + unsigned n = id >> ITARGETSR_SHIFT; + return mmio_read_32(base + GICD_ITARGETSR + (n << 2)); +} + +unsigned int gicd_read_icfgr(unsigned int base, unsigned int id) +{ + unsigned n = id >> ICFGR_SHIFT; + return mmio_read_32(base + GICD_ICFGR + (n << 2)); +} + +unsigned int gicd_read_sgir(unsigned int base) +{ + return mmio_read_32(base + GICD_SGIR); +} + +unsigned int gicd_read_cpendsgir(unsigned int base, unsigned int id) +{ + unsigned n = id >> CPENDSGIR_SHIFT; + return mmio_read_32(base + GICD_CPENDSGIR + (n << 2)); +} + +unsigned int gicd_read_spendsgir(unsigned int base, unsigned int id) +{ + unsigned n = id >> SPENDSGIR_SHIFT; + return mmio_read_32(base + GICD_SPENDSGIR + (n << 2)); +} + +/******************************************************************************* + * GIC Distributor interface accessesors for writing entire registers + ******************************************************************************/ +inline void gicd_write_ctlr(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICD_CTLR, val); + return; +} + +void gicd_write_igroupr(unsigned int base, unsigned int id, unsigned int val) +{ + unsigned n = id >> IGROUPR_SHIFT; + mmio_write_32(base + GICD_IGROUPR + (n << 2), val); + return; +} + +void gicd_write_isenabler(unsigned int base, unsigned int id, unsigned int val) +{ + unsigned n = id >> ISENABLER_SHIFT; + mmio_write_32(base + GICD_ISENABLER + (n << 2), val); + return; +} + +void gicd_write_icenabler(unsigned int base, unsigned int id, unsigned int val) +{ + unsigned n = id >> ICENABLER_SHIFT; + mmio_write_32(base + GICD_ICENABLER + (n << 2), val); + return; +} + +void gicd_write_ispendr(unsigned int base, unsigned int id, unsigned int val) +{ + unsigned n = id >> ISPENDR_SHIFT; + mmio_write_32(base + GICD_ISPENDR + (n << 2), val); + return; +} + +void gicd_write_icpendr(unsigned int base, unsigned int id, unsigned int val) +{ + unsigned n = id >> ICPENDR_SHIFT; + mmio_write_32(base + GICD_ICPENDR + (n << 2), val); + return; +} + +void gicd_write_isactiver(unsigned int base, unsigned int id, unsigned int val) +{ + unsigned n = id >> ISACTIVER_SHIFT; + mmio_write_32(base + GICD_ISACTIVER + (n << 2), val); + return; +} + +void gicd_write_icactiver(unsigned int base, unsigned int id, unsigned int val) +{ + unsigned n = id >> ICACTIVER_SHIFT; + mmio_write_32(base + GICD_ICACTIVER + (n << 2), val); + return; +} + +void gicd_write_ipriorityr(unsigned int base, unsigned int id, unsigned int val) +{ + unsigned n = id >> IPRIORITYR_SHIFT; + mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val); + return; +} + +void gicd_write_itargetsr(unsigned int base, unsigned int id, unsigned int val) +{ + unsigned n = id >> ITARGETSR_SHIFT; + mmio_write_32(base + GICD_ITARGETSR + (n << 2), val); + return; +} + +void gicd_write_icfgr(unsigned int base, unsigned int id, unsigned int val) +{ + unsigned n = id >> ICFGR_SHIFT; + mmio_write_32(base + GICD_ICFGR + (n << 2), val); + return; +} + +void gicd_write_sgir(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICD_SGIR, val); + return; +} + +void gicd_write_cpendsgir(unsigned int base, unsigned int id, unsigned int val) +{ + unsigned n = id >> CPENDSGIR_SHIFT; + mmio_write_32(base + GICD_CPENDSGIR + (n << 2), val); + return; +} + +void gicd_write_spendsgir(unsigned int base, unsigned int id, unsigned int val) +{ + unsigned n = id >> SPENDSGIR_SHIFT; + mmio_write_32(base + GICD_SPENDSGIR + (n << 2), val); + return; +} + +/******************************************************************************* + * GIC Distributor interface accessesors for individual interrupt manipulation + ******************************************************************************/ +unsigned int gicd_get_igroupr(unsigned int base, unsigned int id) +{ + unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1); + unsigned int reg_val = gicd_read_igroupr(base, id); + + return (reg_val >> bit_num) & 0x1; +} + +void gicd_set_igroupr(unsigned int base, unsigned int id) +{ + unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1); + unsigned int reg_val = gicd_read_igroupr(base, id); + + gicd_write_igroupr(base, id, reg_val | (1 << bit_num)); + return; +} + +void gicd_clr_igroupr(unsigned int base, unsigned int id) +{ + unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1); + unsigned int reg_val = gicd_read_igroupr(base, id); + + gicd_write_igroupr(base, id, reg_val & ~(1 << bit_num)); + return; +} + +void gicd_set_isenabler(unsigned int base, unsigned int id) +{ + unsigned bit_num = id & ((1 << ISENABLER_SHIFT) - 1); + unsigned int reg_val = gicd_read_isenabler(base, id); + + gicd_write_isenabler(base, id, reg_val | (1 << bit_num)); + return; +} + +void gicd_set_icenabler(unsigned int base, unsigned int id) +{ + unsigned bit_num = id & ((1 << ICENABLER_SHIFT) - 1); + unsigned int reg_val = gicd_read_icenabler(base, id); + + gicd_write_icenabler(base, id, reg_val & ~(1 << bit_num)); + return; +} + +void gicd_set_ispendr(unsigned int base, unsigned int id) +{ + unsigned bit_num = id & ((1 << ISPENDR_SHIFT) - 1); + unsigned int reg_val = gicd_read_ispendr(base, id); + + gicd_write_ispendr(base, id, reg_val | (1 << bit_num)); + return; +} + +void gicd_set_icpendr(unsigned int base, unsigned int id) +{ + unsigned bit_num = id & ((1 << ICPENDR_SHIFT) - 1); + unsigned int reg_val = gicd_read_icpendr(base, id); + + gicd_write_icpendr(base, id, reg_val & ~(1 << bit_num)); + return; +} + +void gicd_set_isactiver(unsigned int base, unsigned int id) +{ + unsigned bit_num = id & ((1 << ISACTIVER_SHIFT) - 1); + unsigned int reg_val = gicd_read_isactiver(base, id); + + gicd_write_isactiver(base, id, reg_val | (1 << bit_num)); + return; +} + +void gicd_set_icactiver(unsigned int base, unsigned int id) +{ + unsigned bit_num = id & ((1 << ICACTIVER_SHIFT) - 1); + unsigned int reg_val = gicd_read_icactiver(base, id); + + gicd_write_icactiver(base, id, reg_val & ~(1 << bit_num)); + return; +} + +/* + * Make sure that the interrupt's group is set before expecting + * this function to do its job correctly. + */ +void gicd_set_ipriorityr(unsigned int base, unsigned int id, unsigned int pri) +{ + unsigned byte_off = id & ((1 << ICACTIVER_SHIFT) - 1); + unsigned int reg_val = gicd_read_icactiver(base, id); + + /* + * Enforce ARM recommendation to manage priority values such + * that group1 interrupts always have a lower priority than + * group0 interrupts + */ + if (gicd_get_igroupr(base, id) == GRP1) + pri |= 1 << 7; + else + pri &= ~(1 << 7); + + gicd_write_icactiver(base, id, reg_val & ~(pri << (byte_off << 3))); + return; +} + +void gicd_set_itargetsr(unsigned int base, unsigned int id, unsigned int iface) +{ + unsigned byte_off = id & ((1 << ITARGETSR_SHIFT) - 1); + unsigned int reg_val = gicd_read_itargetsr(base, id); + + gicd_write_itargetsr(base, id, reg_val | + (1 << iface) << (byte_off << 3)); + return; +} + +/******************************************************************************* + * GIC CPU interface accessesors for reading entire registers + ******************************************************************************/ +inline unsigned int gicc_read_ctlr(unsigned int base) +{ + return mmio_read_32(base + GICC_CTLR); +} + +inline unsigned int gicc_read_pmr(unsigned int base) +{ + return mmio_read_32(base + GICC_PMR); +} + +inline unsigned int gicc_read_BPR(unsigned int base) +{ + return mmio_read_32(base + GICC_BPR); +} + +inline unsigned int gicc_read_IAR(unsigned int base) +{ + return mmio_read_32(base + GICC_IAR); +} + +inline unsigned int gicc_read_EOIR(unsigned int base) +{ + return mmio_read_32(base + GICC_EOIR); +} + +inline unsigned int gicc_read_hppir(unsigned int base) +{ + return mmio_read_32(base + GICC_HPPIR); +} + +inline unsigned int gicc_read_dir(unsigned int base) +{ + return mmio_read_32(base + GICC_DIR); +} + +inline unsigned int gicc_read_iidr(unsigned int base) +{ + return mmio_read_32(base + GICC_IIDR); +} + +/******************************************************************************* + * GIC CPU interface accessesors for writing entire registers + ******************************************************************************/ +inline void gicc_write_ctlr(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICC_CTLR, val); + return; +} + +inline void gicc_write_pmr(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICC_PMR, val); + return; +} + +inline void gicc_write_BPR(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICC_BPR, val); + return; +} + +inline void gicc_write_IAR(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICC_IAR, val); + return; +} + +inline void gicc_write_EOIR(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICC_EOIR, val); + return; +} + +inline void gicc_write_hppir(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICC_HPPIR, val); + return; +} + +inline void gicc_write_dir(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICC_DIR, val); + return; +} + diff --git a/arch/system/gic/gic_v3.c b/arch/system/gic/gic_v3.c new file mode 100644 index 0000000..7806a0d --- /dev/null +++ b/arch/system/gic/gic_v3.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013, ARM Limited. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 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. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +#include <gic.h> +#include <mmio.h> + +/******************************************************************************* + * GIC Redistributor interface accessesors + ******************************************************************************/ +inline unsigned int gicr_read_waker(unsigned int base) +{ + return mmio_read_32(base + GICR_WAKER); +} + +inline void gicr_write_waker(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICR_WAKER, val); + return; +} |