linux/arch/arm/include/asm/arch_gicv3.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * arch/arm/include/asm/arch_gicv3.h
   4 *
   5 * Copyright (C) 2015 ARM Ltd.
   6 */
   7#ifndef __ASM_ARCH_GICV3_H
   8#define __ASM_ARCH_GICV3_H
   9
  10#ifndef __ASSEMBLY__
  11
  12#include <linux/io.h>
  13#include <linux/io-64-nonatomic-lo-hi.h>
  14#include <asm/barrier.h>
  15#include <asm/cacheflush.h>
  16#include <asm/cp15.h>
  17
  18#define ICC_EOIR1                       __ACCESS_CP15(c12, 0, c12, 1)
  19#define ICC_DIR                         __ACCESS_CP15(c12, 0, c11, 1)
  20#define ICC_IAR1                        __ACCESS_CP15(c12, 0, c12, 0)
  21#define ICC_SGI1R                       __ACCESS_CP15_64(0, c12)
  22#define ICC_PMR                         __ACCESS_CP15(c4, 0, c6, 0)
  23#define ICC_CTLR                        __ACCESS_CP15(c12, 0, c12, 4)
  24#define ICC_SRE                         __ACCESS_CP15(c12, 0, c12, 5)
  25#define ICC_IGRPEN1                     __ACCESS_CP15(c12, 0, c12, 7)
  26#define ICC_BPR1                        __ACCESS_CP15(c12, 0, c12, 3)
  27#define ICC_RPR                         __ACCESS_CP15(c12, 0, c11, 3)
  28
  29#define __ICC_AP0Rx(x)                  __ACCESS_CP15(c12, 0, c8, 4 | x)
  30#define ICC_AP0R0                       __ICC_AP0Rx(0)
  31#define ICC_AP0R1                       __ICC_AP0Rx(1)
  32#define ICC_AP0R2                       __ICC_AP0Rx(2)
  33#define ICC_AP0R3                       __ICC_AP0Rx(3)
  34
  35#define __ICC_AP1Rx(x)                  __ACCESS_CP15(c12, 0, c9, x)
  36#define ICC_AP1R0                       __ICC_AP1Rx(0)
  37#define ICC_AP1R1                       __ICC_AP1Rx(1)
  38#define ICC_AP1R2                       __ICC_AP1Rx(2)
  39#define ICC_AP1R3                       __ICC_AP1Rx(3)
  40
  41#define CPUIF_MAP(a32, a64)                     \
  42static inline void write_ ## a64(u32 val)       \
  43{                                               \
  44        write_sysreg(val, a32);                 \
  45}                                               \
  46static inline u32 read_ ## a64(void)            \
  47{                                               \
  48        return read_sysreg(a32);                \
  49}                                               \
  50
  51CPUIF_MAP(ICC_PMR, ICC_PMR_EL1)
  52CPUIF_MAP(ICC_AP0R0, ICC_AP0R0_EL1)
  53CPUIF_MAP(ICC_AP0R1, ICC_AP0R1_EL1)
  54CPUIF_MAP(ICC_AP0R2, ICC_AP0R2_EL1)
  55CPUIF_MAP(ICC_AP0R3, ICC_AP0R3_EL1)
  56CPUIF_MAP(ICC_AP1R0, ICC_AP1R0_EL1)
  57CPUIF_MAP(ICC_AP1R1, ICC_AP1R1_EL1)
  58CPUIF_MAP(ICC_AP1R2, ICC_AP1R2_EL1)
  59CPUIF_MAP(ICC_AP1R3, ICC_AP1R3_EL1)
  60
  61#define read_gicreg(r)                 read_##r()
  62#define write_gicreg(v, r)             write_##r(v)
  63
  64/* Low-level accessors */
  65
  66static inline void gic_write_eoir(u32 irq)
  67{
  68        write_sysreg(irq, ICC_EOIR1);
  69        isb();
  70}
  71
  72static inline void gic_write_dir(u32 val)
  73{
  74        write_sysreg(val, ICC_DIR);
  75        isb();
  76}
  77
  78static inline u32 gic_read_iar(void)
  79{
  80        u32 irqstat = read_sysreg(ICC_IAR1);
  81
  82        dsb(sy);
  83
  84        return irqstat;
  85}
  86
  87static inline void gic_write_ctlr(u32 val)
  88{
  89        write_sysreg(val, ICC_CTLR);
  90        isb();
  91}
  92
  93static inline u32 gic_read_ctlr(void)
  94{
  95        return read_sysreg(ICC_CTLR);
  96}
  97
  98static inline void gic_write_grpen1(u32 val)
  99{
 100        write_sysreg(val, ICC_IGRPEN1);
 101        isb();
 102}
 103
 104static inline void gic_write_sgi1r(u64 val)
 105{
 106        write_sysreg(val, ICC_SGI1R);
 107}
 108
 109static inline u32 gic_read_sre(void)
 110{
 111        return read_sysreg(ICC_SRE);
 112}
 113
 114static inline void gic_write_sre(u32 val)
 115{
 116        write_sysreg(val, ICC_SRE);
 117        isb();
 118}
 119
 120static inline void gic_write_bpr1(u32 val)
 121{
 122        write_sysreg(val, ICC_BPR1);
 123}
 124
 125static inline u32 gic_read_pmr(void)
 126{
 127        return read_sysreg(ICC_PMR);
 128}
 129
 130static inline void gic_write_pmr(u32 val)
 131{
 132        write_sysreg(val, ICC_PMR);
 133}
 134
 135static inline u32 gic_read_rpr(void)
 136{
 137        return read_sysreg(ICC_RPR);
 138}
 139
 140/*
 141 * Even in 32bit systems that use LPAE, there is no guarantee that the I/O
 142 * interface provides true 64bit atomic accesses, so using strd/ldrd doesn't
 143 * make much sense.
 144 * Moreover, 64bit I/O emulation is extremely difficult to implement on
 145 * AArch32, since the syndrome register doesn't provide any information for
 146 * them.
 147 * Consequently, the following IO helpers use 32bit accesses.
 148 */
 149static inline void __gic_writeq_nonatomic(u64 val, volatile void __iomem *addr)
 150{
 151        writel_relaxed((u32)val, addr);
 152        writel_relaxed((u32)(val >> 32), addr + 4);
 153}
 154
 155static inline u64 __gic_readq_nonatomic(const volatile void __iomem *addr)
 156{
 157        u64 val;
 158
 159        val = readl_relaxed(addr);
 160        val |= (u64)readl_relaxed(addr + 4) << 32;
 161        return val;
 162}
 163
 164#define gic_flush_dcache_to_poc(a,l)    __cpuc_flush_dcache_area((a), (l))
 165
 166/*
 167 *  GICD_IROUTERn, contain the affinity values associated to each interrupt.
 168 *  The upper-word (aff3) will always be 0, so there is no need for a lock.
 169 */
 170#define gic_write_irouter(v, c)         __gic_writeq_nonatomic(v, c)
 171
 172/*
 173 * GICR_TYPER is an ID register and doesn't need atomicity.
 174 */
 175#define gic_read_typer(c)               __gic_readq_nonatomic(c)
 176
 177/*
 178 * GITS_BASER - hi and lo bits may be accessed independently.
 179 */
 180#define gits_read_baser(c)              __gic_readq_nonatomic(c)
 181#define gits_write_baser(v, c)          __gic_writeq_nonatomic(v, c)
 182
 183/*
 184 * GICR_PENDBASER and GICR_PROPBASE are changed with LPIs disabled, so they
 185 * won't be being used during any updates and can be changed non-atomically
 186 */
 187#define gicr_read_propbaser(c)          __gic_readq_nonatomic(c)
 188#define gicr_write_propbaser(v, c)      __gic_writeq_nonatomic(v, c)
 189#define gicr_read_pendbaser(c)          __gic_readq_nonatomic(c)
 190#define gicr_write_pendbaser(v, c)      __gic_writeq_nonatomic(v, c)
 191
 192/*
 193 * GICR_xLPIR - only the lower bits are significant
 194 */
 195#define gic_read_lpir(c)                readl_relaxed(c)
 196#define gic_write_lpir(v, c)            writel_relaxed(lower_32_bits(v), c)
 197
 198/*
 199 * GITS_TYPER is an ID register and doesn't need atomicity.
 200 */
 201#define gits_read_typer(c)              __gic_readq_nonatomic(c)
 202
 203/*
 204 * GITS_CBASER - hi and lo bits may be accessed independently.
 205 */
 206#define gits_read_cbaser(c)             __gic_readq_nonatomic(c)
 207#define gits_write_cbaser(v, c)         __gic_writeq_nonatomic(v, c)
 208
 209/*
 210 * GITS_CWRITER - hi and lo bits may be accessed independently.
 211 */
 212#define gits_write_cwriter(v, c)        __gic_writeq_nonatomic(v, c)
 213
 214/*
 215 * GICR_VPROPBASER - hi and lo bits may be accessed independently.
 216 */
 217#define gicr_read_vpropbaser(c)         __gic_readq_nonatomic(c)
 218#define gicr_write_vpropbaser(v, c)     __gic_writeq_nonatomic(v, c)
 219
 220/*
 221 * GICR_VPENDBASER - the Valid bit must be cleared before changing
 222 * anything else.
 223 */
 224static inline void gicr_write_vpendbaser(u64 val, void __iomem *addr)
 225{
 226        u32 tmp;
 227
 228        tmp = readl_relaxed(addr + 4);
 229        if (tmp & (GICR_VPENDBASER_Valid >> 32)) {
 230                tmp &= ~(GICR_VPENDBASER_Valid >> 32);
 231                writel_relaxed(tmp, addr + 4);
 232        }
 233
 234        /*
 235         * Use the fact that __gic_writeq_nonatomic writes the second
 236         * half of the 64bit quantity after the first.
 237         */
 238        __gic_writeq_nonatomic(val, addr);
 239}
 240
 241#define gicr_read_vpendbaser(c)         __gic_readq_nonatomic(c)
 242
 243static inline bool gic_prio_masking_enabled(void)
 244{
 245        return false;
 246}
 247
 248static inline void gic_pmr_mask_irqs(void)
 249{
 250        /* Should not get called. */
 251        WARN_ON_ONCE(true);
 252}
 253
 254static inline void gic_arch_enable_irqs(void)
 255{
 256        /* Should not get called. */
 257        WARN_ON_ONCE(true);
 258}
 259
 260#endif /* !__ASSEMBLY__ */
 261#endif /* !__ASM_ARCH_GICV3_H */
 262