mips-gic.h (12387B)
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__ */