linux/arch/mips/include/asm/mips-gic.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-or-later */
   2/*
   3 * Copyright (C) 2017 Imagination Technologies
   4 * Author: Paul Burton <paul.burton@mips.com>
   5 */
   6
   7#ifndef __MIPS_ASM_MIPS_CPS_H__
   8# error Please include asm/mips-cps.h rather than asm/mips-gic.h
   9#endif
  10
  11#ifndef __MIPS_ASM_MIPS_GIC_H__
  12#define __MIPS_ASM_MIPS_GIC_H__
  13
  14#include <linux/bitops.h>
  15
  16/* The base address of the GIC registers */
  17extern void __iomem *mips_gic_base;
  18
  19/* Offsets from the GIC base address to various control blocks */
  20#define MIPS_GIC_SHARED_OFS     0x00000
  21#define MIPS_GIC_SHARED_SZ      0x08000
  22#define MIPS_GIC_LOCAL_OFS      0x08000
  23#define MIPS_GIC_LOCAL_SZ       0x04000
  24#define MIPS_GIC_REDIR_OFS      0x0c000
  25#define MIPS_GIC_REDIR_SZ       0x04000
  26#define MIPS_GIC_USER_OFS       0x10000
  27#define MIPS_GIC_USER_SZ        0x10000
  28
  29/* For read-only shared registers */
  30#define GIC_ACCESSOR_RO(sz, off, name)                                  \
  31        CPS_ACCESSOR_RO(gic, sz, MIPS_GIC_SHARED_OFS + off, name)
  32
  33/* For read-write shared registers */
  34#define GIC_ACCESSOR_RW(sz, off, name)                                  \
  35        CPS_ACCESSOR_RW(gic, sz, MIPS_GIC_SHARED_OFS + off, name)
  36
  37/* For read-only local registers */
  38#define GIC_VX_ACCESSOR_RO(sz, off, name)                               \
  39        CPS_ACCESSOR_RO(gic, sz, MIPS_GIC_LOCAL_OFS + off, vl_##name)   \
  40        CPS_ACCESSOR_RO(gic, sz, MIPS_GIC_REDIR_OFS + off, vo_##name)
  41
  42/* For read-write local registers */
  43#define GIC_VX_ACCESSOR_RW(sz, off, name)                               \
  44        CPS_ACCESSOR_RW(gic, sz, MIPS_GIC_LOCAL_OFS + off, vl_##name)   \
  45        CPS_ACCESSOR_RW(gic, sz, MIPS_GIC_REDIR_OFS + off, vo_##name)
  46
  47/* For read-only shared per-interrupt registers */
  48#define GIC_ACCESSOR_RO_INTR_REG(sz, off, stride, name)                 \
  49static inline void __iomem *addr_gic_##name(unsigned int intr)          \
  50{                                                                       \
  51        return mips_gic_base + (off) + (intr * (stride));               \
  52}                                                                       \
  53                                                                        \
  54static inline unsigned int read_gic_##name(unsigned int intr)           \
  55{                                                                       \
  56        BUILD_BUG_ON(sz != 32);                                         \
  57        return __raw_readl(addr_gic_##name(intr));                      \
  58}
  59
  60/* For read-write shared per-interrupt registers */
  61#define GIC_ACCESSOR_RW_INTR_REG(sz, off, stride, name)                 \
  62        GIC_ACCESSOR_RO_INTR_REG(sz, off, stride, name)                 \
  63                                                                        \
  64static inline void write_gic_##name(unsigned int intr,                  \
  65                                    unsigned int val)                   \
  66{                                                                       \
  67        BUILD_BUG_ON(sz != 32);                                         \
  68        __raw_writel(val, addr_gic_##name(intr));                       \
  69}
  70
  71/* For read-only local per-interrupt registers */
  72#define GIC_VX_ACCESSOR_RO_INTR_REG(sz, off, stride, name)              \
  73        GIC_ACCESSOR_RO_INTR_REG(sz, MIPS_GIC_LOCAL_OFS + off,          \
  74                                 stride, vl_##name)                     \
  75        GIC_ACCESSOR_RO_INTR_REG(sz, MIPS_GIC_REDIR_OFS + off,          \
  76                                 stride, vo_##name)
  77
  78/* For read-write local per-interrupt registers */
  79#define GIC_VX_ACCESSOR_RW_INTR_REG(sz, off, stride, name)              \
  80        GIC_ACCESSOR_RW_INTR_REG(sz, MIPS_GIC_LOCAL_OFS + off,          \
  81                                 stride, vl_##name)                     \
  82        GIC_ACCESSOR_RW_INTR_REG(sz, MIPS_GIC_REDIR_OFS + off,          \
  83                                 stride, vo_##name)
  84
  85/* For read-only shared bit-per-interrupt registers */
  86#define GIC_ACCESSOR_RO_INTR_BIT(off, name)                             \
  87static inline void __iomem *addr_gic_##name(void)                       \
  88{                                                                       \
  89        return mips_gic_base + (off);                                   \
  90}                                                                       \
  91                                                                        \
  92static inline unsigned int read_gic_##name(unsigned int intr)           \
  93{                                                                       \
  94        void __iomem *addr = addr_gic_##name();                         \
  95        unsigned int val;                                               \
  96                                                                        \
  97        if (mips_cm_is64) {                                             \
  98                addr += (intr / 64) * sizeof(uint64_t);                 \
  99                val = __raw_readq(addr) >> intr % 64;                   \
 100        } else {                                                        \
 101                addr += (intr / 32) * sizeof(uint32_t);                 \
 102                val = __raw_readl(addr) >> intr % 32;                   \
 103        }                                                               \
 104                                                                        \
 105        return val & 0x1;                                               \
 106}
 107
 108/* For read-write shared bit-per-interrupt registers */
 109#define GIC_ACCESSOR_RW_INTR_BIT(off, name)                             \
 110        GIC_ACCESSOR_RO_INTR_BIT(off, name)                             \
 111                                                                        \
 112static inline void write_gic_##name(unsigned int intr)                  \
 113{                                                                       \
 114        void __iomem *addr = addr_gic_##name();                         \
 115                                                                        \
 116        if (mips_cm_is64) {                                             \
 117                addr += (intr / 64) * sizeof(uint64_t);                 \
 118                __raw_writeq(BIT(intr % 64), addr);                     \
 119        } else {                                                        \
 120                addr += (intr / 32) * sizeof(uint32_t);                 \
 121                __raw_writel(BIT(intr % 32), addr);                     \
 122        }                                                               \
 123}                                                                       \
 124                                                                        \
 125static inline void change_gic_##name(unsigned int intr,                 \
 126                                     unsigned int val)                  \
 127{                                                                       \
 128        void __iomem *addr = addr_gic_##name();                         \
 129                                                                        \
 130        if (mips_cm_is64) {                                             \
 131                uint64_t _val;                                          \
 132                                                                        \
 133                addr += (intr / 64) * sizeof(uint64_t);                 \
 134                _val = __raw_readq(addr);                               \
 135                _val &= ~BIT_ULL(intr % 64);                            \
 136                _val |= (uint64_t)val << (intr % 64);                   \
 137                __raw_writeq(_val, addr);                               \
 138        } else {                                                        \
 139                uint32_t _val;                                          \
 140                                                                        \
 141                addr += (intr / 32) * sizeof(uint32_t);                 \
 142                _val = __raw_readl(addr);                               \
 143                _val &= ~BIT(intr % 32);                                \
 144                _val |= val << (intr % 32);                             \
 145                __raw_writel(_val, addr);                               \
 146        }                                                               \
 147}
 148
 149/* For read-only local bit-per-interrupt registers */
 150#define GIC_VX_ACCESSOR_RO_INTR_BIT(sz, off, name)                      \
 151        GIC_ACCESSOR_RO_INTR_BIT(sz, MIPS_GIC_LOCAL_OFS + off,          \
 152                                 vl_##name)                             \
 153        GIC_ACCESSOR_RO_INTR_BIT(sz, MIPS_GIC_REDIR_OFS + off,          \
 154                                 vo_##name)
 155
 156/* For read-write local bit-per-interrupt registers */
 157#define GIC_VX_ACCESSOR_RW_INTR_BIT(sz, off, name)                      \
 158        GIC_ACCESSOR_RW_INTR_BIT(sz, MIPS_GIC_LOCAL_OFS + off,          \
 159                                 vl_##name)                             \
 160        GIC_ACCESSOR_RW_INTR_BIT(sz, MIPS_GIC_REDIR_OFS + off,          \
 161                                 vo_##name)
 162
 163/* GIC_SH_CONFIG - Information about the GIC configuration */
 164GIC_ACCESSOR_RW(32, 0x000, config)
 165#define GIC_CONFIG_COUNTSTOP            BIT(28)
 166#define GIC_CONFIG_COUNTBITS            GENMASK(27, 24)
 167#define GIC_CONFIG_NUMINTERRUPTS        GENMASK(23, 16)
 168#define GIC_CONFIG_PVPS                 GENMASK(6, 0)
 169
 170/* GIC_SH_COUNTER - Shared global counter value */
 171GIC_ACCESSOR_RW(64, 0x010, counter)
 172GIC_ACCESSOR_RW(32, 0x010, counter_32l)
 173GIC_ACCESSOR_RW(32, 0x014, counter_32h)
 174
 175/* GIC_SH_POL_* - Configures interrupt polarity */
 176GIC_ACCESSOR_RW_INTR_BIT(0x100, pol)
 177#define GIC_POL_ACTIVE_LOW              0       /* when level triggered */
 178#define GIC_POL_ACTIVE_HIGH             1       /* when level triggered */
 179#define GIC_POL_FALLING_EDGE            0       /* when single-edge triggered */
 180#define GIC_POL_RISING_EDGE             1       /* when single-edge triggered */
 181
 182/* GIC_SH_TRIG_* - Configures interrupts to be edge or level triggered */
 183GIC_ACCESSOR_RW_INTR_BIT(0x180, trig)
 184#define GIC_TRIG_LEVEL                  0
 185#define GIC_TRIG_EDGE                   1
 186
 187/* GIC_SH_DUAL_* - Configures whether interrupts trigger on both edges */
 188GIC_ACCESSOR_RW_INTR_BIT(0x200, dual)
 189#define GIC_DUAL_SINGLE                 0       /* when edge-triggered */
 190#define GIC_DUAL_DUAL                   1       /* when edge-triggered */
 191
 192/* GIC_SH_WEDGE - Write an 'edge', ie. trigger an interrupt */
 193GIC_ACCESSOR_RW(32, 0x280, wedge)
 194#define GIC_WEDGE_RW                    BIT(31)
 195#define GIC_WEDGE_INTR                  GENMASK(7, 0)
 196
 197/* GIC_SH_RMASK_* - Reset/clear shared interrupt mask bits */
 198GIC_ACCESSOR_RW_INTR_BIT(0x300, rmask)
 199
 200/* GIC_SH_SMASK_* - Set shared interrupt mask bits */
 201GIC_ACCESSOR_RW_INTR_BIT(0x380, smask)
 202
 203/* GIC_SH_MASK_* - Read the current shared interrupt mask */
 204GIC_ACCESSOR_RO_INTR_BIT(0x400, mask)
 205
 206/* GIC_SH_PEND_* - Read currently pending shared interrupts */
 207GIC_ACCESSOR_RO_INTR_BIT(0x480, pend)
 208
 209/* GIC_SH_MAPx_PIN - Map shared interrupts to a particular CPU pin */
 210GIC_ACCESSOR_RW_INTR_REG(32, 0x500, 0x4, map_pin)
 211#define GIC_MAP_PIN_MAP_TO_PIN          BIT(31)
 212#define GIC_MAP_PIN_MAP_TO_NMI          BIT(30)
 213#define GIC_MAP_PIN_MAP                 GENMASK(5, 0)
 214
 215/* GIC_SH_MAPx_VP - Map shared interrupts to a particular Virtual Processor */
 216GIC_ACCESSOR_RW_INTR_REG(32, 0x2000, 0x20, map_vp)
 217
 218/* GIC_Vx_CTL - VP-level interrupt control */
 219GIC_VX_ACCESSOR_RW(32, 0x000, ctl)
 220#define GIC_VX_CTL_FDC_ROUTABLE         BIT(4)
 221#define GIC_VX_CTL_SWINT_ROUTABLE       BIT(3)
 222#define GIC_VX_CTL_PERFCNT_ROUTABLE     BIT(2)
 223#define GIC_VX_CTL_TIMER_ROUTABLE       BIT(1)
 224#define GIC_VX_CTL_EIC                  BIT(0)
 225
 226/* GIC_Vx_PEND - Read currently pending local interrupts */
 227GIC_VX_ACCESSOR_RO(32, 0x004, pend)
 228
 229/* GIC_Vx_MASK - Read the current local interrupt mask */
 230GIC_VX_ACCESSOR_RO(32, 0x008, mask)
 231
 232/* GIC_Vx_RMASK - Reset/clear local interrupt mask bits */
 233GIC_VX_ACCESSOR_RW(32, 0x00c, rmask)
 234
 235/* GIC_Vx_SMASK - Set local interrupt mask bits */
 236GIC_VX_ACCESSOR_RW(32, 0x010, smask)
 237
 238/* GIC_Vx_*_MAP - Route local interrupts to the desired pins */
 239GIC_VX_ACCESSOR_RW_INTR_REG(32, 0x040, 0x4, map)
 240
 241/* GIC_Vx_WD_MAP - Route the local watchdog timer interrupt */
 242GIC_VX_ACCESSOR_RW(32, 0x040, wd_map)
 243
 244/* GIC_Vx_COMPARE_MAP - Route the local count/compare interrupt */
 245GIC_VX_ACCESSOR_RW(32, 0x044, compare_map)
 246
 247/* GIC_Vx_TIMER_MAP - Route the local CPU timer (cp0 count/compare) interrupt */
 248GIC_VX_ACCESSOR_RW(32, 0x048, timer_map)
 249
 250/* GIC_Vx_FDC_MAP - Route the local fast debug channel interrupt */
 251GIC_VX_ACCESSOR_RW(32, 0x04c, fdc_map)
 252
 253/* GIC_Vx_PERFCTR_MAP - Route the local performance counter interrupt */
 254GIC_VX_ACCESSOR_RW(32, 0x050, perfctr_map)
 255
 256/* GIC_Vx_SWINT0_MAP - Route the local software interrupt 0 */
 257GIC_VX_ACCESSOR_RW(32, 0x054, swint0_map)
 258
 259/* GIC_Vx_SWINT1_MAP - Route the local software interrupt 1 */
 260GIC_VX_ACCESSOR_RW(32, 0x058, swint1_map)
 261
 262/* GIC_Vx_OTHER - Configure access to other Virtual Processor registers */
 263GIC_VX_ACCESSOR_RW(32, 0x080, other)
 264#define GIC_VX_OTHER_VPNUM              GENMASK(5, 0)
 265
 266/* GIC_Vx_IDENT - Retrieve the local Virtual Processor's ID */
 267GIC_VX_ACCESSOR_RO(32, 0x088, ident)
 268#define GIC_VX_IDENT_VPNUM              GENMASK(5, 0)
 269
 270/* GIC_Vx_COMPARE - Value to compare with GIC_SH_COUNTER */
 271GIC_VX_ACCESSOR_RW(64, 0x0a0, compare)
 272
 273/* GIC_Vx_EIC_SHADOW_SET_BASE - Set shadow register set for each interrupt */
 274GIC_VX_ACCESSOR_RW_INTR_REG(32, 0x100, 0x4, eic_shadow_set)
 275
 276/**
 277 * enum mips_gic_local_interrupt - GIC local interrupts
 278 * @GIC_LOCAL_INT_WD: GIC watchdog timer interrupt
 279 * @GIC_LOCAL_INT_COMPARE: GIC count/compare interrupt
 280 * @GIC_LOCAL_INT_TIMER: CP0 count/compare interrupt
 281 * @GIC_LOCAL_INT_PERFCTR: Performance counter interrupt
 282 * @GIC_LOCAL_INT_SWINT0: Software interrupt 0
 283 * @GIC_LOCAL_INT_SWINT1: Software interrupt 1
 284 * @GIC_LOCAL_INT_FDC: Fast debug channel interrupt
 285 * @GIC_NUM_LOCAL_INTRS: The number of local interrupts
 286 *
 287 * Enumerates interrupts provided by the GIC that are local to a VP.
 288 */
 289enum mips_gic_local_interrupt {
 290        GIC_LOCAL_INT_WD,
 291        GIC_LOCAL_INT_COMPARE,
 292        GIC_LOCAL_INT_TIMER,
 293        GIC_LOCAL_INT_PERFCTR,
 294        GIC_LOCAL_INT_SWINT0,
 295        GIC_LOCAL_INT_SWINT1,
 296        GIC_LOCAL_INT_FDC,
 297        GIC_NUM_LOCAL_INTRS
 298};
 299
 300/**
 301 * mips_gic_present() - Determine whether a GIC is present
 302 *
 303 * Determines whether a MIPS Global Interrupt Controller (GIC) is present in
 304 * the system that the kernel is running on.
 305 *
 306 * Return true if a GIC is present, else false.
 307 */
 308static inline bool mips_gic_present(void)
 309{
 310        return IS_ENABLED(CONFIG_MIPS_GIC) && mips_gic_base;
 311}
 312
 313/**
 314 * mips_gic_vx_map_reg() - Return GIC_Vx_<intr>_MAP register offset
 315 * @intr: A GIC local interrupt
 316 *
 317 * Determine the index of the GIC_VL_<intr>_MAP or GIC_VO_<intr>_MAP register
 318 * within the block of GIC map registers. This is almost the same as the order
 319 * of interrupts in the pending & mask registers, as used by enum
 320 * mips_gic_local_interrupt, but moves the FDC interrupt & thus offsets the
 321 * interrupts after it...
 322 *
 323 * Return: The map register index corresponding to @intr.
 324 *
 325 * The return value is suitable for use with the (read|write)_gic_v[lo]_map
 326 * accessor functions.
 327 */
 328static inline unsigned int
 329mips_gic_vx_map_reg(enum mips_gic_local_interrupt intr)
 330{
 331        /* WD, Compare & Timer are 1:1 */
 332        if (intr <= GIC_LOCAL_INT_TIMER)
 333                return intr;
 334
 335        /* FDC moves to after Timer... */
 336        if (intr == GIC_LOCAL_INT_FDC)
 337                return GIC_LOCAL_INT_TIMER + 1;
 338
 339        /* As a result everything else is offset by 1 */
 340        return intr + 1;
 341}
 342
 343/**
 344 * gic_get_c0_compare_int() - Return cp0 count/compare interrupt virq
 345 *
 346 * Determine the virq number to use for the coprocessor 0 count/compare
 347 * interrupt, which may be routed via the GIC.
 348 *
 349 * Returns the virq number or a negative error number.
 350 */
 351extern int gic_get_c0_compare_int(void);
 352
 353/**
 354 * gic_get_c0_perfcount_int() - Return performance counter interrupt virq
 355 *
 356 * Determine the virq number to use for CPU performance counter interrupts,
 357 * which may be routed via the GIC.
 358 *
 359 * Returns the virq number or a negative error number.
 360 */
 361extern int gic_get_c0_perfcount_int(void);
 362
 363/**
 364 * gic_get_c0_fdc_int() - Return fast debug channel interrupt virq
 365 *
 366 * Determine the virq number to use for fast debug channel (FDC) interrupts,
 367 * which may be routed via the GIC.
 368 *
 369 * Returns the virq number or a negative error number.
 370 */
 371extern int gic_get_c0_fdc_int(void);
 372
 373#endif /* __MIPS_ASM_MIPS_CPS_H__ */
 374