Paul Burton | 582e2b4 | 2017-08-12 21:36:10 -0700 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright (C) 2017 Imagination Technologies |
| 3 | * Author: Paul Burton <paul.burton@imgtec.com> |
| 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of the GNU General Public License as published by the |
| 7 | * Free Software Foundation; either version 2 of the License, or (at your |
| 8 | * option) any later version. |
| 9 | */ |
| 10 | |
| 11 | #ifndef __MIPS_ASM_MIPS_CPS_H__ |
| 12 | # error Please include asm/mips-cps.h rather than asm/mips-gic.h |
| 13 | #endif |
| 14 | |
| 15 | #ifndef __MIPS_ASM_MIPS_GIC_H__ |
| 16 | #define __MIPS_ASM_MIPS_GIC_H__ |
| 17 | |
| 18 | #include <linux/bitops.h> |
| 19 | |
| 20 | /* The base address of the GIC registers */ |
| 21 | extern void __iomem *mips_gic_base; |
| 22 | |
| 23 | /* Offsets from the GIC base address to various control blocks */ |
| 24 | #define MIPS_GIC_SHARED_OFS 0x00000 |
| 25 | #define MIPS_GIC_SHARED_SZ 0x08000 |
| 26 | #define MIPS_GIC_LOCAL_OFS 0x08000 |
| 27 | #define MIPS_GIC_LOCAL_SZ 0x04000 |
| 28 | #define MIPS_GIC_REDIR_OFS 0x0c000 |
| 29 | #define MIPS_GIC_REDIR_SZ 0x04000 |
| 30 | #define MIPS_GIC_USER_OFS 0x10000 |
| 31 | #define MIPS_GIC_USER_SZ 0x10000 |
| 32 | |
| 33 | /* For read-only shared registers */ |
| 34 | #define GIC_ACCESSOR_RO(sz, off, name) \ |
| 35 | CPS_ACCESSOR_RO(gic, sz, MIPS_GIC_SHARED_OFS + off, name) |
| 36 | |
| 37 | /* For read-write shared registers */ |
| 38 | #define GIC_ACCESSOR_RW(sz, off, name) \ |
| 39 | CPS_ACCESSOR_RW(gic, sz, MIPS_GIC_SHARED_OFS + off, name) |
| 40 | |
| 41 | /* For read-only local registers */ |
| 42 | #define GIC_VX_ACCESSOR_RO(sz, off, name) \ |
| 43 | CPS_ACCESSOR_RO(gic, sz, MIPS_GIC_LOCAL_OFS + off, vl_##name) \ |
| 44 | CPS_ACCESSOR_RO(gic, sz, MIPS_GIC_REDIR_OFS + off, vo_##name) |
| 45 | |
| 46 | /* For read-write local registers */ |
| 47 | #define GIC_VX_ACCESSOR_RW(sz, off, name) \ |
| 48 | CPS_ACCESSOR_RW(gic, sz, MIPS_GIC_LOCAL_OFS + off, vl_##name) \ |
| 49 | CPS_ACCESSOR_RW(gic, sz, MIPS_GIC_REDIR_OFS + off, vo_##name) |
| 50 | |
| 51 | /* For read-only shared per-interrupt registers */ |
| 52 | #define GIC_ACCESSOR_RO_INTR_REG(sz, off, stride, name) \ |
| 53 | static inline void __iomem *addr_gic_##name(unsigned int intr) \ |
| 54 | { \ |
| 55 | return mips_gic_base + (off) + (intr * (stride)); \ |
| 56 | } \ |
| 57 | \ |
| 58 | static inline unsigned int read_gic_##name(unsigned int intr) \ |
| 59 | { \ |
| 60 | BUILD_BUG_ON(sz != 32); \ |
| 61 | return __raw_readl(addr_gic_##name(intr)); \ |
| 62 | } |
| 63 | |
| 64 | /* For read-write shared per-interrupt registers */ |
| 65 | #define GIC_ACCESSOR_RW_INTR_REG(sz, off, stride, name) \ |
| 66 | GIC_ACCESSOR_RO_INTR_REG(sz, off, stride, name) \ |
| 67 | \ |
| 68 | static inline void write_gic_##name(unsigned int intr, \ |
| 69 | unsigned int val) \ |
| 70 | { \ |
| 71 | BUILD_BUG_ON(sz != 32); \ |
| 72 | __raw_writel(val, addr_gic_##name(intr)); \ |
| 73 | } |
| 74 | |
| 75 | /* For read-only local per-interrupt registers */ |
| 76 | #define GIC_VX_ACCESSOR_RO_INTR_REG(sz, off, stride, name) \ |
| 77 | GIC_ACCESSOR_RO_INTR_REG(sz, MIPS_GIC_LOCAL_OFS + off, \ |
| 78 | stride, vl_##name) \ |
| 79 | GIC_ACCESSOR_RO_INTR_REG(sz, MIPS_GIC_REDIR_OFS + off, \ |
| 80 | stride, vo_##name) |
| 81 | |
| 82 | /* For read-write local per-interrupt registers */ |
| 83 | #define GIC_VX_ACCESSOR_RW_INTR_REG(sz, off, stride, name) \ |
| 84 | GIC_ACCESSOR_RW_INTR_REG(sz, MIPS_GIC_LOCAL_OFS + off, \ |
| 85 | stride, vl_##name) \ |
| 86 | GIC_ACCESSOR_RW_INTR_REG(sz, MIPS_GIC_REDIR_OFS + off, \ |
| 87 | stride, vo_##name) |
| 88 | |
| 89 | /* For read-only shared bit-per-interrupt registers */ |
| 90 | #define GIC_ACCESSOR_RO_INTR_BIT(off, name) \ |
| 91 | static inline void __iomem *addr_gic_##name(void) \ |
| 92 | { \ |
| 93 | return mips_gic_base + (off); \ |
| 94 | } \ |
| 95 | \ |
| 96 | static inline unsigned int read_gic_##name(unsigned int intr) \ |
| 97 | { \ |
| 98 | void __iomem *addr = addr_gic_##name(); \ |
| 99 | unsigned int val; \ |
| 100 | \ |
| 101 | if (mips_cm_is64) { \ |
| 102 | addr += (intr / 64) * sizeof(uint64_t); \ |
| 103 | val = __raw_readq(addr) >> intr % 64; \ |
| 104 | } else { \ |
| 105 | addr += (intr / 32) * sizeof(uint32_t); \ |
| 106 | val = __raw_readl(addr) >> intr % 32; \ |
| 107 | } \ |
| 108 | \ |
| 109 | return val & 0x1; \ |
| 110 | } |
| 111 | |
| 112 | /* For read-write shared bit-per-interrupt registers */ |
| 113 | #define GIC_ACCESSOR_RW_INTR_BIT(off, name) \ |
| 114 | GIC_ACCESSOR_RO_INTR_BIT(off, name) \ |
| 115 | \ |
| 116 | static inline void write_gic_##name(unsigned int intr) \ |
| 117 | { \ |
| 118 | void __iomem *addr = addr_gic_##name(); \ |
| 119 | \ |
| 120 | if (mips_cm_is64) { \ |
| 121 | addr += (intr / 64) * sizeof(uint64_t); \ |
| 122 | __raw_writeq(BIT(intr % 64), addr); \ |
| 123 | } else { \ |
| 124 | addr += (intr / 32) * sizeof(uint32_t); \ |
| 125 | __raw_writel(BIT(intr % 32), addr); \ |
| 126 | } \ |
| 127 | } \ |
| 128 | \ |
| 129 | static inline void change_gic_##name(unsigned int intr, \ |
| 130 | unsigned int val) \ |
| 131 | { \ |
| 132 | void __iomem *addr = addr_gic_##name(); \ |
| 133 | \ |
| 134 | if (mips_cm_is64) { \ |
| 135 | uint64_t _val; \ |
| 136 | \ |
| 137 | addr += (intr / 64) * sizeof(uint64_t); \ |
| 138 | _val = __raw_readq(addr); \ |
| 139 | _val &= ~BIT_ULL(intr % 64); \ |
| 140 | _val |= (uint64_t)val << (intr % 64); \ |
| 141 | __raw_writeq(_val, addr); \ |
| 142 | } else { \ |
| 143 | uint32_t _val; \ |
| 144 | \ |
| 145 | addr += (intr / 32) * sizeof(uint32_t); \ |
| 146 | _val = __raw_readl(addr); \ |
| 147 | _val &= ~BIT(intr % 32); \ |
| 148 | _val |= val << (intr % 32); \ |
| 149 | __raw_writel(_val, addr); \ |
| 150 | } \ |
| 151 | } |
| 152 | |
| 153 | /* For read-only local bit-per-interrupt registers */ |
| 154 | #define GIC_VX_ACCESSOR_RO_INTR_BIT(sz, off, name) \ |
| 155 | GIC_ACCESSOR_RO_INTR_BIT(sz, MIPS_GIC_LOCAL_OFS + off, \ |
| 156 | vl_##name) \ |
| 157 | GIC_ACCESSOR_RO_INTR_BIT(sz, MIPS_GIC_REDIR_OFS + off, \ |
| 158 | vo_##name) |
| 159 | |
| 160 | /* For read-write local bit-per-interrupt registers */ |
| 161 | #define GIC_VX_ACCESSOR_RW_INTR_BIT(sz, off, name) \ |
| 162 | GIC_ACCESSOR_RW_INTR_BIT(sz, MIPS_GIC_LOCAL_OFS + off, \ |
| 163 | vl_##name) \ |
| 164 | GIC_ACCESSOR_RW_INTR_BIT(sz, MIPS_GIC_REDIR_OFS + off, \ |
| 165 | vo_##name) |
| 166 | |
| 167 | /* GIC_SH_CONFIG - Information about the GIC configuration */ |
| 168 | GIC_ACCESSOR_RW(32, 0x000, config) |
| 169 | #define GIC_CONFIG_COUNTSTOP BIT(28) |
| 170 | #define GIC_CONFIG_COUNTBITS GENMASK(27, 24) |
| 171 | #define GIC_CONFIG_NUMINTERRUPTS GENMASK(23, 16) |
| 172 | #define GIC_CONFIG_PVPS GENMASK(6, 0) |
| 173 | |
| 174 | /* GIC_SH_COUNTER - Shared global counter value */ |
| 175 | GIC_ACCESSOR_RW(64, 0x010, counter) |
| 176 | GIC_ACCESSOR_RW(32, 0x010, counter_32l) |
| 177 | GIC_ACCESSOR_RW(32, 0x014, counter_32h) |
| 178 | |
| 179 | /* GIC_SH_POL_* - Configures interrupt polarity */ |
| 180 | GIC_ACCESSOR_RW_INTR_BIT(0x100, pol) |
| 181 | #define GIC_POL_ACTIVE_LOW 0 /* when level triggered */ |
| 182 | #define GIC_POL_ACTIVE_HIGH 1 /* when level triggered */ |
| 183 | #define GIC_POL_FALLING_EDGE 0 /* when single-edge triggered */ |
| 184 | #define GIC_POL_RISING_EDGE 1 /* when single-edge triggered */ |
| 185 | |
| 186 | /* GIC_SH_TRIG_* - Configures interrupts to be edge or level triggered */ |
| 187 | GIC_ACCESSOR_RW_INTR_BIT(0x180, trig) |
| 188 | #define GIC_TRIG_LEVEL 0 |
| 189 | #define GIC_TRIG_EDGE 1 |
| 190 | |
| 191 | /* GIC_SH_DUAL_* - Configures whether interrupts trigger on both edges */ |
| 192 | GIC_ACCESSOR_RW_INTR_BIT(0x200, dual) |
| 193 | #define GIC_DUAL_SINGLE 0 /* when edge-triggered */ |
| 194 | #define GIC_DUAL_DUAL 1 /* when edge-triggered */ |
| 195 | |
| 196 | /* GIC_SH_WEDGE - Write an 'edge', ie. trigger an interrupt */ |
| 197 | GIC_ACCESSOR_RW(32, 0x280, wedge) |
| 198 | #define GIC_WEDGE_RW BIT(31) |
| 199 | #define GIC_WEDGE_INTR GENMASK(7, 0) |
| 200 | |
| 201 | /* GIC_SH_RMASK_* - Reset/clear shared interrupt mask bits */ |
| 202 | GIC_ACCESSOR_RW_INTR_BIT(0x300, rmask) |
| 203 | |
| 204 | /* GIC_SH_SMASK_* - Set shared interrupt mask bits */ |
| 205 | GIC_ACCESSOR_RW_INTR_BIT(0x380, smask) |
| 206 | |
| 207 | /* GIC_SH_MASK_* - Read the current shared interrupt mask */ |
| 208 | GIC_ACCESSOR_RO_INTR_BIT(0x400, mask) |
| 209 | |
| 210 | /* GIC_SH_PEND_* - Read currently pending shared interrupts */ |
| 211 | GIC_ACCESSOR_RO_INTR_BIT(0x480, pend) |
| 212 | |
| 213 | /* GIC_SH_MAPx_PIN - Map shared interrupts to a particular CPU pin */ |
| 214 | GIC_ACCESSOR_RW_INTR_REG(32, 0x500, 0x4, map_pin) |
| 215 | #define GIC_MAP_PIN_MAP_TO_PIN BIT(31) |
| 216 | #define GIC_MAP_PIN_MAP_TO_NMI BIT(30) |
| 217 | #define GIC_MAP_PIN_MAP GENMASK(5, 0) |
| 218 | |
| 219 | /* GIC_SH_MAPx_VP - Map shared interrupts to a particular Virtual Processor */ |
| 220 | GIC_ACCESSOR_RW_INTR_REG(32, 0x2000, 0x20, map_vp) |
| 221 | |
| 222 | /* GIC_Vx_CTL - VP-level interrupt control */ |
| 223 | GIC_VX_ACCESSOR_RW(32, 0x000, ctl) |
| 224 | #define GIC_VX_CTL_FDC_ROUTABLE BIT(4) |
| 225 | #define GIC_VX_CTL_SWINT_ROUTABLE BIT(3) |
| 226 | #define GIC_VX_CTL_PERFCNT_ROUTABLE BIT(2) |
| 227 | #define GIC_VX_CTL_TIMER_ROUTABLE BIT(1) |
| 228 | #define GIC_VX_CTL_EIC BIT(0) |
| 229 | |
| 230 | /* GIC_Vx_PEND - Read currently pending local interrupts */ |
| 231 | GIC_VX_ACCESSOR_RO(32, 0x004, pend) |
| 232 | |
| 233 | /* GIC_Vx_MASK - Read the current local interrupt mask */ |
| 234 | GIC_VX_ACCESSOR_RO(32, 0x008, mask) |
| 235 | |
| 236 | /* GIC_Vx_RMASK - Reset/clear local interrupt mask bits */ |
| 237 | GIC_VX_ACCESSOR_RW(32, 0x00c, rmask) |
| 238 | |
| 239 | /* GIC_Vx_SMASK - Set local interrupt mask bits */ |
| 240 | GIC_VX_ACCESSOR_RW(32, 0x010, smask) |
| 241 | |
| 242 | /* GIC_Vx_*_MAP - Route local interrupts to the desired pins */ |
| 243 | GIC_VX_ACCESSOR_RW_INTR_REG(32, 0x040, 0x4, map) |
| 244 | |
| 245 | /* GIC_Vx_WD_MAP - Route the local watchdog timer interrupt */ |
| 246 | GIC_VX_ACCESSOR_RW(32, 0x040, wd_map) |
| 247 | |
| 248 | /* GIC_Vx_COMPARE_MAP - Route the local count/compare interrupt */ |
| 249 | GIC_VX_ACCESSOR_RW(32, 0x044, compare_map) |
| 250 | |
| 251 | /* GIC_Vx_TIMER_MAP - Route the local CPU timer (cp0 count/compare) interrupt */ |
| 252 | GIC_VX_ACCESSOR_RW(32, 0x048, timer_map) |
| 253 | |
| 254 | /* GIC_Vx_FDC_MAP - Route the local fast debug channel interrupt */ |
| 255 | GIC_VX_ACCESSOR_RW(32, 0x04c, fdc_map) |
| 256 | |
| 257 | /* GIC_Vx_PERFCTR_MAP - Route the local performance counter interrupt */ |
| 258 | GIC_VX_ACCESSOR_RW(32, 0x050, perfctr_map) |
| 259 | |
| 260 | /* GIC_Vx_SWINT0_MAP - Route the local software interrupt 0 */ |
| 261 | GIC_VX_ACCESSOR_RW(32, 0x054, swint0_map) |
| 262 | |
| 263 | /* GIC_Vx_SWINT1_MAP - Route the local software interrupt 1 */ |
| 264 | GIC_VX_ACCESSOR_RW(32, 0x058, swint1_map) |
| 265 | |
| 266 | /* GIC_Vx_OTHER - Configure access to other Virtual Processor registers */ |
| 267 | GIC_VX_ACCESSOR_RW(32, 0x080, other) |
| 268 | #define GIC_VX_OTHER_VPNUM GENMASK(5, 0) |
| 269 | |
| 270 | /* GIC_Vx_IDENT - Retrieve the local Virtual Processor's ID */ |
| 271 | GIC_VX_ACCESSOR_RO(32, 0x088, ident) |
| 272 | #define GIC_VX_IDENT_VPNUM GENMASK(5, 0) |
| 273 | |
| 274 | /* GIC_Vx_COMPARE - Value to compare with GIC_SH_COUNTER */ |
| 275 | GIC_VX_ACCESSOR_RW(64, 0x0a0, compare) |
| 276 | |
| 277 | /* GIC_Vx_EIC_SHADOW_SET_BASE - Set shadow register set for each interrupt */ |
| 278 | GIC_VX_ACCESSOR_RW_INTR_REG(32, 0x100, 0x4, eic_shadow_set) |
| 279 | |
| 280 | /** |
| 281 | * mips_gic_present() - Determine whether a GIC is present |
| 282 | * |
| 283 | * Determines whether a MIPS Global Interrupt Controller (GIC) is present in |
| 284 | * the system that the kernel is running on. |
| 285 | * |
| 286 | * Return true if a GIC is present, else false. |
| 287 | */ |
| 288 | static inline bool mips_gic_present(void) |
| 289 | { |
| 290 | return IS_ENABLED(CONFIG_MIPS_GIC) && mips_gic_base; |
| 291 | } |
| 292 | |
| 293 | #endif /* __MIPS_ASM_MIPS_CPS_H__ */ |