Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * arch/arm64/include/asm/arch_gicv3.h
0004  *
0005  * Copyright (C) 2015 ARM Ltd.
0006  */
0007 #ifndef __ASM_ARCH_GICV3_H
0008 #define __ASM_ARCH_GICV3_H
0009 
0010 #include <asm/sysreg.h>
0011 
0012 #ifndef __ASSEMBLY__
0013 
0014 #include <linux/irqchip/arm-gic-common.h>
0015 #include <linux/stringify.h>
0016 #include <asm/barrier.h>
0017 #include <asm/cacheflush.h>
0018 
0019 #define read_gicreg(r)          read_sysreg_s(SYS_ ## r)
0020 #define write_gicreg(v, r)      write_sysreg_s(v, SYS_ ## r)
0021 
0022 /*
0023  * Low-level accessors
0024  *
0025  * These system registers are 32 bits, but we make sure that the compiler
0026  * sets the GP register's most significant bits to 0 with an explicit cast.
0027  */
0028 
0029 static __always_inline void gic_write_dir(u32 irq)
0030 {
0031     write_sysreg_s(irq, SYS_ICC_DIR_EL1);
0032     isb();
0033 }
0034 
0035 static inline u64 gic_read_iar_common(void)
0036 {
0037     u64 irqstat;
0038 
0039     irqstat = read_sysreg_s(SYS_ICC_IAR1_EL1);
0040     dsb(sy);
0041     return irqstat;
0042 }
0043 
0044 /*
0045  * Cavium ThunderX erratum 23154
0046  *
0047  * The gicv3 of ThunderX requires a modified version for reading the
0048  * IAR status to ensure data synchronization (access to icc_iar1_el1
0049  * is not sync'ed before and after).
0050  *
0051  * Erratum 38545
0052  *
0053  * When a IAR register read races with a GIC interrupt RELEASE event,
0054  * GIC-CPU interface could wrongly return a valid INTID to the CPU
0055  * for an interrupt that is already released(non activated) instead of 0x3ff.
0056  *
0057  * To workaround this, return a valid interrupt ID only if there is a change
0058  * in the active priority list after the IAR read.
0059  *
0060  * Common function used for both the workarounds since,
0061  * 1. On Thunderx 88xx 1.x both erratas are applicable.
0062  * 2. Having extra nops doesn't add any side effects for Silicons where
0063  *    erratum 23154 is not applicable.
0064  */
0065 static inline u64 gic_read_iar_cavium_thunderx(void)
0066 {
0067     u64 irqstat, apr;
0068 
0069     apr = read_sysreg_s(SYS_ICC_AP1R0_EL1);
0070     nops(8);
0071     irqstat = read_sysreg_s(SYS_ICC_IAR1_EL1);
0072     nops(4);
0073     mb();
0074 
0075     /* Max priority groups implemented is only 32 */
0076     if (likely(apr != read_sysreg_s(SYS_ICC_AP1R0_EL1)))
0077         return irqstat;
0078 
0079     return 0x3ff;
0080 }
0081 
0082 static inline void gic_write_ctlr(u32 val)
0083 {
0084     write_sysreg_s(val, SYS_ICC_CTLR_EL1);
0085     isb();
0086 }
0087 
0088 static inline u32 gic_read_ctlr(void)
0089 {
0090     return read_sysreg_s(SYS_ICC_CTLR_EL1);
0091 }
0092 
0093 static inline void gic_write_grpen1(u32 val)
0094 {
0095     write_sysreg_s(val, SYS_ICC_IGRPEN1_EL1);
0096     isb();
0097 }
0098 
0099 static inline void gic_write_sgi1r(u64 val)
0100 {
0101     write_sysreg_s(val, SYS_ICC_SGI1R_EL1);
0102 }
0103 
0104 static inline u32 gic_read_sre(void)
0105 {
0106     return read_sysreg_s(SYS_ICC_SRE_EL1);
0107 }
0108 
0109 static inline void gic_write_sre(u32 val)
0110 {
0111     write_sysreg_s(val, SYS_ICC_SRE_EL1);
0112     isb();
0113 }
0114 
0115 static inline void gic_write_bpr1(u32 val)
0116 {
0117     write_sysreg_s(val, SYS_ICC_BPR1_EL1);
0118 }
0119 
0120 static inline u32 gic_read_pmr(void)
0121 {
0122     return read_sysreg_s(SYS_ICC_PMR_EL1);
0123 }
0124 
0125 static __always_inline void gic_write_pmr(u32 val)
0126 {
0127     write_sysreg_s(val, SYS_ICC_PMR_EL1);
0128 }
0129 
0130 static inline u32 gic_read_rpr(void)
0131 {
0132     return read_sysreg_s(SYS_ICC_RPR_EL1);
0133 }
0134 
0135 #define gic_read_typer(c)       readq_relaxed(c)
0136 #define gic_write_irouter(v, c)     writeq_relaxed(v, c)
0137 #define gic_read_lpir(c)        readq_relaxed(c)
0138 #define gic_write_lpir(v, c)        writeq_relaxed(v, c)
0139 
0140 #define gic_flush_dcache_to_poc(a,l)    \
0141     dcache_clean_inval_poc((unsigned long)(a), (unsigned long)(a)+(l))
0142 
0143 #define gits_read_baser(c)      readq_relaxed(c)
0144 #define gits_write_baser(v, c)      writeq_relaxed(v, c)
0145 
0146 #define gits_read_cbaser(c)     readq_relaxed(c)
0147 #define gits_write_cbaser(v, c)     writeq_relaxed(v, c)
0148 
0149 #define gits_write_cwriter(v, c)    writeq_relaxed(v, c)
0150 
0151 #define gicr_read_propbaser(c)      readq_relaxed(c)
0152 #define gicr_write_propbaser(v, c)  writeq_relaxed(v, c)
0153 
0154 #define gicr_write_pendbaser(v, c)  writeq_relaxed(v, c)
0155 #define gicr_read_pendbaser(c)      readq_relaxed(c)
0156 
0157 #define gicr_write_vpropbaser(v, c) writeq_relaxed(v, c)
0158 #define gicr_read_vpropbaser(c)     readq_relaxed(c)
0159 
0160 #define gicr_write_vpendbaser(v, c) writeq_relaxed(v, c)
0161 #define gicr_read_vpendbaser(c)     readq_relaxed(c)
0162 
0163 static inline bool gic_prio_masking_enabled(void)
0164 {
0165     return system_uses_irq_prio_masking();
0166 }
0167 
0168 static inline void gic_pmr_mask_irqs(void)
0169 {
0170     BUILD_BUG_ON(GICD_INT_DEF_PRI < (__GIC_PRIO_IRQOFF |
0171                      GIC_PRIO_PSR_I_SET));
0172     BUILD_BUG_ON(GICD_INT_DEF_PRI >= GIC_PRIO_IRQON);
0173     /*
0174      * Need to make sure IRQON allows IRQs when SCR_EL3.FIQ is cleared
0175      * and non-secure PMR accesses are not subject to the shifts that
0176      * are applied to IRQ priorities
0177      */
0178     BUILD_BUG_ON((0x80 | (GICD_INT_DEF_PRI >> 1)) >= GIC_PRIO_IRQON);
0179     /*
0180      * Same situation as above, but now we make sure that we can mask
0181      * regular interrupts.
0182      */
0183     BUILD_BUG_ON((0x80 | (GICD_INT_DEF_PRI >> 1)) < (__GIC_PRIO_IRQOFF_NS |
0184                              GIC_PRIO_PSR_I_SET));
0185     gic_write_pmr(GIC_PRIO_IRQOFF);
0186 }
0187 
0188 static inline void gic_arch_enable_irqs(void)
0189 {
0190     asm volatile ("msr daifclr, #3" : : : "memory");
0191 }
0192 
0193 #endif /* __ASSEMBLY__ */
0194 #endif /* __ASM_ARCH_GICV3_H */